Readability可读性
1.Asking for permission instead of forgiveness
EAFP (easier to ask for forgiveness than permission)
假设需要的变量/文件文件, 如果有问题则捕获异常
1
2
3
4
5
6
7
8
9
10
11
12
| # Bad
import os
if os.path.exists("file.txt"):
os.unlink("file.txt")
# Great
import os
try:
os.unlink("file.txt")
# raised when file does not exist
except OSError:
pass
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| # Bad
person = {
'first': 'Tobin',
'age':20
}
print('{0} is {1} years old'.format(person['first'], person['age']))
# Great
person = {
'first': 'Tobin',
'age':20
}
print('{first} is {age} years old'.format(**person))
|
3.Not using named tuples when returning more than one value from a function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # Bad
def get_name():
return "Richard", "Xavier", "Jones"
name = get_name()
# no idea what these indexes map to!
print(name[0], name[1], name[2])
# Great
from collections import namedtuple
def get_name():
name = namedtuple("name", ["first", "middle", "last"])
return name("Richard", "Xavier", "Jones")
name = get_name()
# much easier to read
print(name.first, name.middle, name.last)
|
4.Not using zip() to iterate over a pair of lists
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # Bad
numbers = [1, 2, 3]
letters = ["A", "B", "C"]
for index in range(len(numbers)):
print(numbers[index], letters[index])
# Great
numbers = [1, 2, 3]
letters = ["A", "B", "C"]
for numbers_value, letters_value in zip(numbers, letters):
print(numbers_value, letters_value)
|
1.Using key in list to check if key is contained in list
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # Bad 每次都需要迭代list然后比较, 复杂率 O(n)
l = [1, 2, 3, 4]
# iterates over three elements in the list
if 3 in l:
print("The number 3 is in the list.")
else:
print("The number 3 is NOT in the list.")
# Great set做了去重, 复杂率O(logn)
# Use a set or dictionary instead of a list
# 单次查询效率 set > dict > list
s = set([1, 2, 3, 4])
if 3 in l:
print("The number 3 is in the list.")
else:
print("The number 3 is NOT in the list.")
|
2.Not using iteritems() to iterate over a large dictionary
只适用于Py2.X, Py3中items默认返回迭代器,iteritems()已经从Py3.x移除
1
2
3
4
5
6
7
8
9
10
11
12
13
| # Bad
d = {i: i * 2 for i in xrange(10000000)}
# Slow and memory hungry.
for key, value in d.items():
print("{0} = {1}".format(key, value))
# Great
d = {i: i * 2 for i in xrange(10000000)}
# Memory efficient.
for key, value in d.iteritems():
print("{0} = {1}".format(key, value))
|
database queries
1
2
3
4
5
6
7
8
| """ views.py """
from models import Cars
# ...
cars = Cars.objects.all()
for car in cars:
do_something(car.make)
|
实际对应执行SQL为
SELECT make, model, wheels, ... FROM vehicles_cars;
如果只需要单取make字段, 数据表数据过大或者单个表字段过多, 则会造成没必要的性能消耗.
优化1
1
2
3
4
5
6
7
8
9
| from cars.models import Cars
cars = Cars.objects.all().values('make')
# Print all makes
# 返回字典
for car in cars:
do_something(car['make'])
|
优化2,返回tuple
1
2
3
4
5
6
7
| from cars.models import Cars
cars = Cars.objects.all().values_list('make', flat=True)
# Print all makes
# 返回元组
for make in cars:
do_something(make)
|
对应的sql
SELECT make from vehicles_cars;
参考: The Little Book of Python Anti-Patterns — Python Anti-Patterns documentation