Python 性能技巧 (二)

本来还想继续翻译:https://wiki.python.org/moin/PythonSpeed/PerformanceTips,但是事情太多真的没时间,那么就简单的总结一下吧。

字符串拼接

应该避免使用:

1
2
3
s = ""
for substring in list:
s += substring

选择使用:

1
s = "".join(list)

对于大字符串列表,避免使用:

1
2
3
s = ""
for x in list:
s += some_function(x)

使用:

1
2
slist = [some_function(elt) for elt in somelist]
s = "".join(slist)

避免使用:

1
out = "<html>" + head + prologue + query + tail + "</html>"

使用:

1
out = "<html>%s%s%s%s</html>" % (head, prologue, query, tail)

当然了,这种更容易读:

1
out = "<html>%(head)s%(prologue)s%(query)s%(tail)s</html>" % locals()

循环

列表里面的每个字符串都变成大写?

1
2
3
newlist = []
for word in oldlist:
newlist.append(word.upper())

试试这种方法:

1
newlist = map(str.upper, oldlist))

或者是:

1
iterator = (s.upper() for s in oldlist)

避免点号

比如说我们想把一个列表一个大写之后到一个新列表,试试下面的:

1
2
3
4
5
upper = str.upper
newlist = []
append = newlist.append
for word in oldlist:
append(upper(word))

本地变量

Python 在访问本地变量时的速度要比全局变量速度更快,比如:

1
2
3
4
5
6
7
def func():
upper = str.upper
newlist = []
append = newlist.append
for word in oldlist:
append(upper(word))
return newlist

初始化字典元素

比如你在初始化一个字典,字典中每个元素是单词和标号:

1
2
3
4
5
wdict = {}
for word in words:
if word not in wdict:
wdict[word] = 0
wdict[word] += 1

那么试试 try-except 吧:

1
2
3
4
5
6
wdict = {}
for word in words:
try:
wdict[word] += 1
except KeyError:
wdict[word] = 1

或者再换一种方式:

1
2
3
4
wdict = {}
get = wdict.get
for word in words:
wdict[word] = get(word, 0) + 1

头部引入

1
2
3
4
5
6
7
8
9
10
11
12
13
def doit1():
import string ###### import statement inside function
string.lower('Python')

for num in range(100000):
doit1()

import string ###### import statement outside function
def doit2():
string.lower('Python')

for num in range(100000):
doit2()

doit2 要快一些。

数据聚合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import time
x = 0
def doit1(i):
global x
x = x + i

list = range(100000)
t = time.time()
for i in list:
doit1(i)

print "%.3f" % (time.time()-t)

vs

import time
x = 0
def doit2(list):
global x
for i in list:
x = x + i

list = range(100000)
t = time.time()
doit2(list)
print "%.3f" % (time.time()-t)

对比一下性能,第二种方法要更快一点

xrange 替代 range

恩,xrage 更快一些。

善用 cProfile

性能诊断的好工具