Be more pythonic
Pyladies Berlin, 2015
by Mei Li Triantafyllidi
Zen of python
PEP8
No tabs
4 spaces indentation
Yes: spam(ham[1], {eggs: 2})
No: spam( ham[ 1 ], { eggs: 2 } )
Whitespaces
Yes: x, y = y, x No: x , y = y , x
Yes: counter = counter + 1 No: counter=counter+1
Yes: result = add(x+1, 3)
Yes: result = add(x + 1, 3)
Yes: import os
import sys
No: import sys, os
No: from subprocess import *
Yes: from subprocess import Popen, PIPE
Import statements
Naming conventions
- lower_case_under for variables and functions and methods
- WordCap for classes
- ALL_CAPS for constants
Tools
- pep8
- pylint
- pyflakes
most IDEs have a plugin
Pythonic code patterns
Swap variables
No:
tmp = b
b = a
a = tmp
Yes:
a, b = b, a
Swap variables more
tmp_x = x + dx * t
tmp_y = y + dy * t
tmp_dx = influence(m, x, y, dx, dy, partial='x')
tmp_dy = influence(m, x, y, dx, dy, partial='y')
x = tmp_x
y = tmp_y
dx = tmp_dx
dy = tmp_dy
No
Yes
x, y, dx, dy = (x + dx * t,
y + dy * t,
influence(m, x, y, dx, dy, partial='x'),
influence(m, x, y, dx, dy, partial='y'))Unpacking tuples
person_info = ("Mary", 27)
## Don't do
name = person_info[0]
age = person_info[1]
## Do
name, age = person_infoIteration
## Don't do
for i in [0, 1, 2, 3, 4]:
print i
## Don't do
for i in range(5):
print i
## Do
for i in xrange(5):
print i
## Python 3 - only range
Iteration over list
colors = ['red', 'green', 'blue', 'yellow']
# Don't do
for i in range(len(colors)):
print colors[i]
# Do
for color in colors:
print color
Iteration over list with index
colors = ['red', 'green', 'blue', 'yellow']
## Don't do
for i in range(len(colors)):
print i, '-->', colors[i]
## Do
for i, color in enumerate(colors):
print i, '-->', colorList comprehension
## Don't do
names = []
for kid in kids:
names.append(kid["name"])
## Do
names = [kid["name"] for kid in kids]
## Don't do
baby_names = []
for kid in kids:
if kid["age"] < 1:
baby_names.append(kid["name"])
## Do
names = [kid["name"] for kid in kids if kid["age"] > 1]Use builtins - sum
## Get sum of all numbers until 100
## Don't do
total = 0
for num in range(101):
total += num
## Do
total = sum(range(101))
## Get sum of all squares of numbers until 100
## Don't do
total = 0
for num in range(101):
total += num**2
## Do
total = sum([n**2 for n in range(101)])Generators
## Don't do
total = sum([n**2 for n in range(101)])
## Do
total = sum(n**2 for n in range(101))Concatenate list strings
## Don't do
s = names[0]
for name in names[1:]:
s += ', ' + name
## Do
s = ', '.join(names)Sort list
names = ["Mary", "John", "Peter", "Helen"]
for name in sorted(names):
print name
## sort by string length
for name in sorted(names, key=len):
print name
## Sorting descending
for name in sorted(names, reverse=True):
print name
Counting with dictionaries
colors = ['red', 'green', 'red', 'blue', 'green', 'red']
# Don't do
d = {}
for color in colors:
if color not in d:
d[color] = 0
d[color] += 1
# {'blue': 1, 'green': 2, 'red': 3}
# Do
d = {}
for color in colors:
d[color] = d.get(color, 0) + 1
Grouping with dictionaries
colors = ['gray', 'black', 'yellow', 'blue', 'green', 'red']
# Don't do
d = {}
for color in colors:
first_char = color[0]
if first_char not in d:
d[first_char] = []
d[first_char].append(color)
# {'r': ['red'], 'b': ['black', 'blue'],
# 'g': ['gray', 'green']}
# Do
d = defaultdict(list)
for color in colors:
first_char = color[0]
d[first_char].append(color)Looping over dictionaries
city_music = {"berlin": "techno",
"seville": "flamenco",
"new york": "jazz"}
# only keys
for city in city_music:
print city
# to change the dictionary while looping - Do
for city in city_music.keys():
if city not in europe:
del city_music[city]
Looping over dictionaries more
city_music = {"berlin": "techno",
"seville": "flamenco",
"new york": "jazz"}
for city in city_music:
print city, 'listens to', city_music[city]
# more readable
for city, music in city_music.items():
print city, 'listens to', music
# more readable and faster
for city, music in city_music.iteritems():
print city, 'listens to', musicReading files
# Do not do
fp = open("notes.txt")
text = fp.read()
fp.close()
# Do
with open("notes.txt") as fp:
text = fp.read()
# read file line by line
with open("notes.txt") as fp:
for line in fp:
print linewhat's next
- decorators
- property instead of getter, setter
- staticmethod, classmethod
resources
Sum up
- Beautiful is better than ugly
- Readability counts
- PEP8
- read builtins, str methods, collections
... so read read read code
Let's practice
http://exercism.io/
Be more pythonic
By Mei Li Triantafyllidi
Be more pythonic
- 890