Beautiful Python
Alicia Pérez
www.stylesage.co
About me

Accent?

We are flying!
>>> import antigravity
Zen of Python
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>>
Strings
colors = ['red', 'blue', 'green', 'yellow']
result = ''
for s in colors:
result += s
# result: 'redbluegreenyellow'
colors = ['red', 'blue', 'green', 'yellow']
result = ''.join(colors)
# result: 'redbluegreenyellow'Good
Bad
Create a string from a list
Strings
colors = ['red', 'blue', 'green', 'yellow']
result = ''
for s in colors:
result += s + ','
result = result[:-1]
# result: 'red,blue,green,yellow'colors = ['red', 'blue', 'green', 'yellow']
result = ','.join(colors)
# result: 'red,blue,green,yellow'Good
Bad
Create a string from a list joined by comma
Strings
my_very_big_string = """For a long time I used to go to bed early. Sometimes,
when I had put out my candle, my eyes would close so quickly that I had not even
time to say "Im going to sleep."""my_very_big_string = (
"For a long time I used to go to bed early. Sometimes, "
"when I had put out my candle, my eyes would close so quickly "
"that I had not even time to say: Im going to sleep."
)Good
Bad
Multi-line
Strings
contains?
stylesage = 'Fashion meets Big Data'
if stylesage.contains('Fashion'):
passBad
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'contains'
Strings
stylesage = 'Fashion meets Big Data'
if stylesage.find("Fashion") != -1:
passGood
Bad
stylesage = 'Fashion meets Big Data'
if 'Fashion' in stylesage:
passcontains in
Strings
format
# OR
'%s %s' % ('one', 'two') '%d %d' % (1, 2)
# output: 'one two' # output: '1 2'New
Old
# OR
'{} {}'.format('one', 'two') '{} {}'.format(1, 2)
# output: 'one two' # output: '1 2'Strings
Basic format
# OR
'%s %s' % ('one', 'two') '%d %d' % (1, 2)
# output: one two # output: 1 2New
Old
# OR
'{} {}'.format('one', 'two') '{} {}'.format(1, 2)
# output: one two # output: one two
# explicit positional index
'{1} {0}'.format('one', 'two')
# output: two oneStrings
Padding and aligning
# OR
'%10s' % ('test',) '%-10s' % ('test',)
# output: ' test' # output: 'test 'New
Old
# OR
'{:>10}'.format('test') '{:10}'.format('test')
# output: ' test' # output: 'test 'Strings
Padding and aligning
# OR
'%10s' % ('test',) '%-10s' % ('test',)
# output: ' test' # output: 'test 'New
Old
# OR
'{:>10}'.format('test') '{:10}'.format('test')
# output: ' test' # output: 'test '
# choose the padding character
'{:_<10}'.format('test')
# output: 'test______'Strings
Padding and aligning
# OR
'%10s' % ('test',) '%-10s' % ('test',)
# output: ' test' # output: 'test 'New
Old
# OR
'{:>10}'.format('test') '{:10}'.format('test')
# output: ' test' # output: 'test '
# choose the padding character
'{:_<10}'.format('test')
# output: 'test______'
# center align value
'{:_^10}'.format('test')
# output: '___test___'Strings
Padding and aligning
New
# This operations are not available with old-style formatting
'{:=5d}'.format((- 23))
# output: '- 23'
'{:%Y-%m-%d %H:%M}'.format(datetime(2001, 2, 3, 4, 5))
# output: '2001-02-03 04:05'
person = {'first': 'Jean-Luc', 'last': 'Picard'}
'{p[first]} {p[last]}'.format(p=person)
# output: 'Jean-Luc Picard'
data = [4, 8, 15, 16, 23, 42]
'{d[4]} {d[5]}'.format(d=data)
# output: '23 42'
tu = (12,45,22222,103,6)
print '{0} {2} {1} {2} {3} {2} {4} {2}'.format(*tu)
# output: '12 22222 45 22222 103 22222 6 22222'
Booleans
if len(items) != 0:
pass
if name != "":
passGood
Bad
if items:
pass
if name:
passCheck if variable equals a constant
| False | True |
|---|---|
| False (== 0) | True (== 1) |
| "" (empty string) | any string but "" (" ", "anything") |
| 0, 0.0 | any number but 0 (1, 0.1, -1, 3.14) |
| [], (), {}, set() | any non-empty container ([0], (None,),['']) |
| None | almost any object that's not explicitly False |
Booleans
Check if variable equals a constant
Booleans
if x >= start and x <= end:
# do stuffGood
Bad
if start <= x <= end:
# do stuffChained comparisons
Comparisons
values = range(10)
i = 0
found = False
while not found and i < len(values):
found = not values[i] % 2
i += 1Good
Bad
values = range(10)
anyPair = any([not value % 2 for value in values])
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# [True, False, True, False, True, False, True, False, True, False]
# anyPair: TrueAny
Comparisons
values = range(10)
i = 0
allPairs = True
while allPairs and i < len(values):
allPairs = not values[i] % 2
i += 1Good
Bad
values = range(10)
allPairs = all([not value % 2 for value in values])
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# [True, False, True, False, True, False, True, False, True, False]
# output: TrueAll
Comparisons
if x > 10:
result = 'Yes'
else:
result = 'No'Good
Bad
result = 'Yes' if x > 10 else 'No'Ternary operator

Lists
mylist = ['yellow', 'red', 'blue', 'green', 'black']
mylist[1:4]
# output: ['red', 'blue', 'green']
mylist[2:]
# output: ['blue', 'green', 'black']
mylist[:2]
# output: ['yellow', 'red']
mylist[-1]
# output: 'black'
mylist[1:-1]
# output: ['red', 'blue', 'green']Manipulation
Lists
a = [3, 4, 5]
for i in range(len(a)):
a[i] += 3Good
Bad
a = [3, 4, 5]
a = [i + 3 for i in a]
# Or:
a = map(lambda i: i + 3, a)List comprehensions
Lists
a = [3, 4, 5]
b = []
for i in a:
if i > 4:
b.append(i)Good
Bad
a = [3, 4, 5]
b = [i for i in a if i > 4]
# Or:
b = filter(lambda x: x > 4, a)Filter
Lists
a = [3, 4, 5]
i = 0
for item in items:
print i, item
i += 1Good
Bad
a = [3, 4, 5]
for i, item in enumerate(a):
print i, itemEnumerate

Generators
def firstn(n):
num, nums = 0, []
while num < n:
nums.append(num)
num += 1
return nums
sum_of_first_n = sum(firstn(1000000))Bad
def firstn(n):
num = 0
while num < n:
yield num
num += 1
sum_of_first_n = sum(firstn(1000000))Good
Not in memory list
Generators
square = [i*i for i in xrange(1000000)]List
square = (i*i for i in irange(1000000))Generator
Generator vs list

Tuples
temp = a
a = b
b = tempb, a = a, bGood
Bad
Swap values
Tuples
l =['David', 'Pythonista', '+1-514-555-1234']
name, title, phone = l
# name: 'David'
# title: 'Pythonista'
# phone: '+1-514-555-1234'Unpacking
Tuples
List of tuples
names = ['John', 'Eric', 'Terry']
surnames = ['Cleese', 'Idle', 'Gilliam']
people = []
for i in range(len(names)):
people.append((names[i], surnames[i]))
print(people)
# output: [('John', 'Cleese'), ('Eric', 'Idle'), ('Terry', 'Gilliam')]names = ['John', 'Eric', 'Terry']
surnames = ['Cleese', 'Idle', 'Gilliam']
zip(names, surnames)
# output: [('John', 'Cleese'), ('Eric', 'Idle'), ('Terry', 'Gilliam')]Good
Bad

Dictionaries
Good
Bad
if d.has_key(key):
print(d[key])if key in d:
print(d[key])Dictionaries
Good
Bad
for key in d.keys():
print keyfor key in d:
print keyExcept
for key in d.keys():
d[str(key)] = d[key]Dictionaries
navs = {}
for (portfolio, equity, position) in data:
if portfolio not in navs:
navs[portfolio] = 0
navs[portfolio] += position * prices[equity]Good
Bad
for (portfolio, equity, position) in data:
navs[portfolio] = (navs.get(portfolio, 0)
+ position * prices[equity])navs = {}
for (portfolio, equity, position) in data:
if portfolio not in navs:
navs[portfolio] = 0
navs[portfolio] += position * prices[equity]for (portfolio, equity, position) in data:
navs.setdefault(portfolio, 0)
navs[portfolio] += position * prices[equity]Dictionaries
Good
Bad
navs = {}
for (portfolio, equity, position) in data:
if portfolio not in navs:
navs[portfolio] = 0
navs[portfolio] += position * prices[equity]navs = defaultdict(int)
for (portfolio, equity, position) in data:
navs[portfolio] += position * prices[equity]Dictionaries
Good
Bad
given = ['John', 'Eric', 'Terry', 'Michael']
family = ['Cleese', 'Idle', 'Gilliam', 'Palin']
pythons = {}
for i in range(len(given)):
pythons[given[i]] = family[i]given = ['John', 'Eric', 'Terry', 'Michael']
family = ['Cleese', 'Idle', 'Gilliam', 'Palin']
pythons = dict(zip(given, family))Dictionaries
Good
Bad
values = range(4)
res = {}
for numb in values:
res[numb] = chr(65 + numb)res = {i : chr(65+i) for i in range(4)}Dictionaries
Good
Bad
{0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}

What!?!?!
Bonus!
Interactive "_"
>>> 1 + 1
2
>>> _
2
>>> import math
>>> math.pi / 3
1.0471975511965976
>>> angle = _
>>> math.cos(angle)
0.50000000000000011
>>> _
0.50000000000000011filename = 'foobar.txt'
basename, _, ext = filename.rpartition('.')Variable "_"

from __future__
>>> from __future__ import braces
File "<stdin>", line 1
SyntaxError: not a chancefrom __future__ import division
print 8/7 # prints 1.1428571428571428
print 8//7 # prints 1We want you!
http://stylesage.co/careers




Questions?
Opinions?
PyCon16 - Beautiful Python
By aliciapj
PyCon16 - Beautiful Python
PyConES 2017
- 3,067