jin5011 发表于 2017-5-5 11:56:35

python 性能测试(1)-- % vs + vs str.join vs +=

网上广为流传着"不要使用+" 连接字符串的“经验”, 特别是这篇文章当中提到了
http://www.oschina.net/question/129540_61768
引用
要使用 out = "<html>%s%s%s%s</html>" % (head, prologue, query, tail)
而避免 out = "<html>" + head + prologue + query + tail + "</html>"

-------
实际上果真如此吗? 连接字符串主要有四种用法:

[*]%
[*]+
[*]str.join
[*]+=

我的理解是这样的
% 和 + 都是应付参数个数已知的、固定的,比如已经知道了a,b,c 三个参数了,那么a+b+c
str.join 和 += 主要是应付参数个数未知的、不固定的,比如参数的一个列表当中所有的字符串,这个列表长度未知;当然他们也可以应付参数个数固定的情况

我的开发环境是:
CPU:Intel(R) Xeon(R) E5520@ 2.27GHz
Memory: 2G
OS: Ubuntu 12.04

第1回合使用
解释器:python 2.7.3
'use % to join' run 1000000 times, spent 2.045571 seconds
'use + ' run 1000000 times, spent 2.238076 seconds

'use str.join ' run 1000000 times, spent 1.816502 seconds
'use += ' run 1000000 times, spent 3.134726 seconds
-----
long items test:
'use % to join' run 1000000 times, spent 3.631465 seconds
'use + ' run 1000000 times, spent 3.203789 seconds
'use str.join ' run 1000000 times, spent 2.474077 seconds
'use += ' run 1000000 times, spent 3.927131 seconds


第2回合使用 pypy, 鉴于使用pypy的人多了起来, 这回是使用ubuntu12 自带的 pypy 1.8
解释器:pypy 1.8 (== python 2.7.2)
short items test:
'use % to join' run 1000000 times, spent 1.637780 seconds
'use + ' run 1000000 times, spent 1.498548 seconds
'use str.join ' run 1000000 times, spent 2.204772 seconds
'use += ' run 1000000 times, spent 2.955786 seconds
-----
long items test:
'use % to join' run 1000000 times, spent 3.570450 seconds
'use + ' run 1000000 times, spent 1.730548 seconds
'use str.join ' run 1000000 times, spent 2.914669 seconds
'use += ' run 1000000 times, spent 5.924469 seconds


第3回合使用 最新的PyPy 2.0 beta1
解释器:pypy 2.0 beta1 (== python 2.7.3)
short items test:
'use % to join' run 1000000 times, spent 0.749635 seconds
'use + ' run 1000000 times, spent 0.423104 seconds
'use str.join ' run 1000000 times, spent 1.319862 seconds
'use += ' run 1000000 times, spent 1.985512 seconds
-----
long items test:
'use % to join' run 1000000 times, spent 2.512883 seconds
'use + ' run 1000000 times, spent 0.414724 seconds
'use str.join ' run 1000000 times, spent 1.934615 seconds
'use += ' run 1000000 times, spent 4.973543 seconds


可以下个结论了:
在纯python上,无论长字符串还是短字符串: 参数个数已知 or 参数个数未知, 都用join吧
如果是pypy, 无论长字符串还是短字符串: 参数个数已知用+ , 未知用join吧; BTW, pypy 2.0beta 的速度确实挺快的

无论哪种情况+哪种解释器,的确是不要用 "+=" !


我的测试代码如下(特别感谢提醒“暗能量有点甜”http://www.weibo.com/kyuseishu 的提示,代码更简洁了):

#!/usr/bin/env python
import time

def show_run_time(name, count, func, args):
start = time.time()
for i in xrange(count):
apply(func, [],args)
print("'%s' run %d times, spent %.6f seconds"%(name, count, time.time()-start))

if __name__ == '__main__':
count = 1000 * 1000
args1 = { #short items
"a": "1"*3,
"b": "2"*4,
"c": "3"*5,
"d": "4"*6,
"e": "5"*7,
"f": "6"*8,
"g": "7"*9,
"h": "8"*10,
}

args2 = { #long items
"a": "1"*101,
"b": "2"*131,
"c": "3"*161,
"d": "4"*191,
"e": "5"*221,
"f": "6"*251,
"g": "7"*281,
"h": "8"*311,
}

def test_str_format(a, b, c, d, e, f, g, h):
out1 = "<html>%s%s%s%s%s%s%s%s</html>" % (a, b, c, d, e, f, g, h)
out2 = "<table>%s%s%s%s%s%s%s%s</table>" % (h, b, c, d, e, f, g, a)
return("%s | %s"%(out1, out2))
def test_plus(a, b, c, d, e, f, g, h):
out1 = "<html>" + a + b+ c + d + e + f + g + b + "</html>"
out2 = "<table>" + h + b+ c + d + e + f + g + a + "</table>"
returnout1 + " | " + out2
def test_plus_and_equal(a, b, c, d, e, f, g, h):
out = "<html>"
for i in :
out += i
out += "</html> | <table>"
for i in :
out += i
out += "</table>"
return out

def test_join(a, b, c, d, e, f, g, h):
out1 = "".join(["<html>", a, b, c, d, e, f, g, h, "</html>"])
out2 = "".join(["<table>", h, b, c, d, e, f, g, a, "</table>"])
return" | ".join((out1, out2))
print "short items test:"
show_run_time("use % to join", count, test_str_format, args1)
show_run_time("use + ", count, test_plus, args1)
show_run_time("use str.join ", count, test_join, args1)
show_run_time("use += ", count, test_plus_and_equal, args1)
print "-----"
print "long items test:"
show_run_time("use % to join", count, test_str_format, args2)
show_run_time("use + ", count, test_plus, args2)
show_run_time("use str.join ", count, test_join, args2)
show_run_time("use += ", count, test_plus_and_equal, args2)
页: [1]
查看完整版本: python 性能测试(1)-- % vs + vs str.join vs +=