网上广为流传着"不要使用+" 连接字符串的“经验”, 特别是这篇文章当中提到了
http://www.oschina.net/question/129540_61768
[quote]要使用 out = "<html>%s%s%s%s</html>" % (head, prologue, query, tail)
而避免 out = "<html>" + head + prologue + query + tail + "</html>"[/quote]
-------
实际上果真如此吗? 连接字符串主要有四种用法:
[list]
[*]%
[*]+
[*]str.join
[*]+=
[/list]
我的理解是这样的
% 和 + 都是应付参数个数已知的、固定的,比如已经知道了a,b,c 三个参数了,那么a+b+c
str.join 和 += 主要是应付参数个数未知的、不固定的,比如参数的一个列表当中所有的字符串,这个列表长度未知;当然他们也可以应付参数个数固定的情况
我的开发环境是:
CPU: Intel(R) Xeon(R) E5520 @ 2.27GHz
Memory: 2G
OS: Ubuntu 12.04
[b]第1回合使用
解释器:python 2.7.3 [/b]
'use % to join' run 1000000 times, spent 2.045571 seconds
'use + ' run 1000000 times, spent 2.238076 seconds
[b]
'use str.join ' run 1000000 times, spent 1.816502 seconds[/b]
'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
[b]'use str.join ' run 1000000 times, spent 2.474077 seconds[/b]
'use += ' run 1000000 times, spent 3.927131 seconds
[b]第2回合使用 pypy, 鉴于使用pypy的人多了起来, 这回是使用ubuntu12 自带的 pypy 1.8
解释器:pypy 1.8 (== python 2.7.2)[/b]
short items test:
'use % to join' run 1000000 times, spent 1.637780 seconds
[b]'use + ' run 1000000 times, spent 1.498548 seconds[/b]
'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
[b]'use + ' run 1000000 times, spent 1.730548 seconds[/b]
'use str.join ' run 1000000 times, spent 2.914669 seconds
'use += ' run 1000000 times, spent 5.924469 seconds
[b]第3回合使用 最新的PyPy 2.0 beta1
解释器:pypy 2.0 beta1 (== python 2.7.3)[/b]
short items test:
'use % to join' run 1000000 times, spent 0.749635 seconds
[b] 'use + ' run 1000000 times, spent 0.423104 seconds [/b]
'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
[b]'use + ' run 1000000 times, spent 0.414724 seconds [/b]
'use str.join ' run 1000000 times, spent 1.934615 seconds
'use += ' run 1000000 times, spent 4.973543 seconds
[size=large]
可以下个结论了:
在纯python上,无论长字符串还是短字符串: 参数个数已知 or 参数个数未知, [b]都用join吧[/b]
如果是pypy, 无论长字符串还是短字符串: 参数个数已知用+ , 未知用join吧; BTW, pypy 2.0beta 的速度确实挺快的
[b] 无论哪种情况+哪种解释器,的确是不要用 "+=" ![/b]
[/size]
我的测试代码如下(特别感谢提醒“暗能量有点甜”http://www.weibo.com/kyuseishu 的提示,代码更简洁了):
http://www.oschina.net/question/129540_61768
[quote]要使用 out = "<html>%s%s%s%s</html>" % (head, prologue, query, tail)
而避免 out = "<html>" + head + prologue + query + tail + "</html>"[/quote]
-------
实际上果真如此吗? 连接字符串主要有四种用法:
[list]
[*]%
[*]+
[*]str.join
[*]+=
[/list]
我的理解是这样的
% 和 + 都是应付参数个数已知的、固定的,比如已经知道了a,b,c 三个参数了,那么a+b+c
str.join 和 += 主要是应付参数个数未知的、不固定的,比如参数的一个列表当中所有的字符串,这个列表长度未知;当然他们也可以应付参数个数固定的情况
我的开发环境是:
CPU: Intel(R) Xeon(R) E5520 @ 2.27GHz
Memory: 2G
OS: Ubuntu 12.04
[b]第1回合使用
解释器:python 2.7.3 [/b]
'use % to join' run 1000000 times, spent 2.045571 seconds
'use + ' run 1000000 times, spent 2.238076 seconds
[b]
'use str.join ' run 1000000 times, spent 1.816502 seconds[/b]
'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
[b]'use str.join ' run 1000000 times, spent 2.474077 seconds[/b]
'use += ' run 1000000 times, spent 3.927131 seconds
[b]第2回合使用 pypy, 鉴于使用pypy的人多了起来, 这回是使用ubuntu12 自带的 pypy 1.8
解释器:pypy 1.8 (== python 2.7.2)[/b]
short items test:
'use % to join' run 1000000 times, spent 1.637780 seconds
[b]'use + ' run 1000000 times, spent 1.498548 seconds[/b]
'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
[b]'use + ' run 1000000 times, spent 1.730548 seconds[/b]
'use str.join ' run 1000000 times, spent 2.914669 seconds
'use += ' run 1000000 times, spent 5.924469 seconds
[b]第3回合使用 最新的PyPy 2.0 beta1
解释器:pypy 2.0 beta1 (== python 2.7.3)[/b]
short items test:
'use % to join' run 1000000 times, spent 0.749635 seconds
[b] 'use + ' run 1000000 times, spent 0.423104 seconds [/b]
'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
[b]'use + ' run 1000000 times, spent 0.414724 seconds [/b]
'use str.join ' run 1000000 times, spent 1.934615 seconds
'use += ' run 1000000 times, spent 4.973543 seconds
[size=large]
可以下个结论了:
在纯python上,无论长字符串还是短字符串: 参数个数已知 or 参数个数未知, [b]都用join吧[/b]
如果是pypy, 无论长字符串还是短字符串: 参数个数已知用+ , 未知用join吧; BTW, pypy 2.0beta 的速度确实挺快的
[b] 无论哪种情况+哪种解释器,的确是不要用 "+=" ![/b]
[/size]
我的测试代码如下(特别感谢提醒“暗能量有点甜”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>"
return out1 + " | " + out2
def test_plus_and_equal(a, b, c, d, e, f, g, h):
out = "<html>"
for i in [a, b, c, d, e, f, g, h]:
out += i
out += "</html> | <table>"
for i in [h, b, c, d, e, f, g, a]:
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)