import sys
print(sys.version_info)
print(sys.version)
sys.version_info(major=3, minor=6, micro=4, releaselevel='final', serial=0) 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)]
Whitepaces
Naming
lowercase_underscore
format_leading_underscore
format.__double_leading_underscore
formatCapitalizedWord
formatALL_CAPS
formatself
as the name of the first parameter, refering to the objectcls
as the name of the first parameter, refering to the classExperessions and Statemens
if a is not b
) instead of negation positive statments (if not a is b
)if len(alist) == 0
). Use if not alist
if
statements, for
, and while
loops, and except
statements. Spread over a series of lines.from bar import foo
) not import foo
See Pylint (http://www.pylint.org/) to analyze your source code and automatically fix it up!
bytes
, str
, and unicode
¶General Python 3
bytes
and str
bytes
contain raw 8-bit values, str
contains unicode#Convert between str and bytes using encode and decode
string = "this is text"
print(string)
bytes_ = string.encode('utf-8')
print("{}".format(bytes_))
string1 = bytes_.decode('utf-8')
print(string1)
print(bytes == string)
print(string == string1)
this is text b'this is text' this is text False True
bytes
and str
are never equivilent#with open('/tmp/random.bin', 'wb') as f:
# f.write(os.urandom(10))
bytes
contain sequences of 8 bit values. str
contains unicode. They can't be used together with operators like >
or +
if
/else
is more readable than or
/and
#Example:
my_values = {'red':[9,8,7]}
print(my_values.get('red', [''])[0] or 0)
print(my_values.get('blue', [''])[0] or 0)
9 0
def get_first_int(values, key, default=0):
found = values.get(key, [''])
if found[0]:
found = int(found[0])
else:
found = default
return found
print(my_values.get('blue', [''])[0] or 0)
0
list
,str
, and bytes
__getitem__
and __setitem__
methods. (Inherticance from collections.abc -- Item 28)alist[start,end]
and start
is inclusive and end
is exclusive.a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print('First four:', a[:4])
print('Last four: ', a[-4:])
print('Middle two:', a[3:-3])
First four: ['a', 'b', 'c', 'd'] Last four: ['e', 'f', 'g', 'h'] Middle two: ['d', 'e']
alist[0:len(alist)]
is redundantb = a[:]
b[0:2] = (1,2)
b[2:4] = ['z','y']
print(b)
print(a)
[1, 2, 'z', 'y', 'e', 'f', 'g', 'h'] ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
b = a[:]
assert b == a and b is not a
start
,end
, and stride
in a single slice¶start
, end
, and stride
in a slice can be confusingstart
or end
indexes and avoid using negative stride
if possiblestart
,end
, and stride
in a single sliceisslice
from itertools
a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(a)
#Bad
b = a[0:6:2]
print(b)
#Good
c = a[0:6]
d = c[::2]
print(d)
assert b == d
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] ['a', 'c', 'e'] ['a', 'c', 'e']
map
and filter
¶map
and filter
because they don't require lambda
functions.a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
squares = [x**2 for x in a]
print(squares)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
even_squares = [x**2 for x in a if x % 2 == 0]
print(even_squares)
#Bad, confusing use of map and filter
alt = map(lambda x: x**2, filter(lambda x: x % 2 == 0, a))
assert even_squares == list(alt)
[4, 16, 36, 64, 100]
chile_ranks = {'ghost': 1, 'habanero': 2, 'cayenne': 3}
rank_dict = {rank: name for name, rank in chile_ranks.items()}
chile_len_set = {len(name) for name in rank_dict.values()}
print(rank_dict)
print(chile_len_set)
{1: 'ghost', 2: 'habanero', 3: 'cayenne'} {8, 5, 7}
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
print(flat)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
squared = [[x**2 for x in row] for row in matrix]
print(squared)
[[1, 4, 9], [16, 25, 36], [49, 64, 81]]
# Additional Examples
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [x for x in a if x > 4 if x % 2 == 0]
c = [x for x in a if x > 4 and x % 2 == 0]
print(a)
print(b)
print(c)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [6, 8, 10] [6, 8, 10]
# Bad
# my_lists = [
# [[1, 2, 3], [4, 5, 6]],
# …
# ] flat =
# [
# x
# for sublist1 in my_lists
# for sublist2 in sublist1
# for x in sublist2]
value = [len(x) for x in open('data/i9_file.txt')]
print(value)
[21, 6, 15, 16, 20]
yeild
values as they're called()
charactersit = (len(x) for x in open('data/i9_file.txt'))
print(it)
<generator object <genexpr> at 0x0000017B4729FD00>
print(next(it))
21
roots = ((x,x**0.5) for x in it)
print(next(roots))
(6, 2.449489742783178)
enumerate
over range
¶range
is useful for loops over a set of integers#random_bits = 0
#for i in range(64):
# if randint(0, 1):
# random_bits |= 1 << i
flavor_list = ['vanilla', 'chocolate', 'pecan', 'strawberry']
for flavor in flavor_list:
print('%s is delicious' % flavor)
vanilla is delicious chocolate is delicious pecan is delicious strawberry is delicious
#Clumsy
for i in range(len(flavor_list)):
flavor = flavor_list[i]
print('%d: %s' % (i + 1, flavor))
1: vanilla 2: chocolate 3: pecan 4: strawberry
# Much better
for i, flavor in enumerate(flavor_list):
print('%d: %s' % (i + 1, flavor))
1: vanilla 2: chocolate 3: pecan 4: strawberry
enumerate
argumentfor i, flavor in enumerate(flavor_list, 1):
print('%d: %s' % (i, flavor))
1: vanilla 2: chocolate 3: pecan 4: strawberry
zip
to Process Iterators in Parallel¶names = ['Cecilia', 'Lise', 'Marie']
letters = [len(n) for n in names]
# Start code
longest_name = None
max_letters = 0
for i in range(len(names)):
count = letters[i]
if count > max_letters:
longest_name = names[i]
max_letters = count
print(longest_name)
Cecilia
# Better
for i, name in enumerate(names):
count = letters[i]
if count > max_letters:
longest_name = name
max_letters = count
print(longest_name)
Cecilia
# Best
for name, count in zip(names, letters):
if count > max_letters:
longest_name = name
max_letters = count
print(longest_name)
Cecilia
zip_longest
from itertools
to iterate over multiple iterators regardless of lengthwhile
and for
)else
only runs if the loop body did not encounter a break statementfor x in []:
print('Never runs')
else:
print('For Else block!')
For Else block!
try
/except
/else
/finally
¶try
/finally
allows for you to run cleanup code regardless of exceptions raised in try
blockelse
helps minimize the amout of code in try
and distinguishes success case from try
/except
blockelse
can be used to perform additional actions after successful try
block but before cleanup in finally
UNDEFINED = object()
def divide_json(path):
handle = open(path, 'r+') # May raise IOError
try:
data = handle.read() # May raise UnicodeDecodeError
op = json.loads(data) # May raise ValueError
value = (
op['numerator'] /
op['denominator']) # May raise ZeroDivisionError
except ZeroDivisionError as e:
return UNDEFINED
else:
op['result'] = value
result = json.dumps(op)
handle.seek(0)
handle.write(result) # May raise IOError
return value
finally:
handle.close() # Always runs