学习了下Google的字符串连接准则,有如下三条:
full_name = prefix + name
result = "result is %s:%d" % (name, score)
result = ''.join(names_tuple)
前两条出于代码美观考虑,后一条出于性能考虑。
使用str.join和使用加号,两种方式在内存使用与性能方式到底有多大差别,写了段测试代码如下:
from time import time
all_str = []
for i in xrange(1, 10000):
all_str.append('100100'*i)
result_str1 = ''
result_str2 = ''
t1 = time()
for i in all_str:
result_str1 = result_str1 + i
t2 = time()
tmp_tup = []
for i in all_str:
tmp_tup.append(i)
result_str2 = ''.join(tmp_tup)
t3 = time()
print("time dist:%f:%f" % (t2-t1, t3-t2))
while 'y' != raw_input('quit?(y)'):
pass
代码最开始产生大量字符串,然后先后使用加号和str.join进行连接, 并分别统计耗时,同时程序末尾不退出,以方便观察内存占用。
首先我们预估一下结果,使用加号进行连接,会导致反复产生新的字符串, 反复进行空间分配与字符串拷贝。而使用str.join会进行优化,不然也不会很多公司的规范里明令禁止使用加号,而强制使用str.join, 既然join的参数是一个数组,做内存的预估计与预分配,也是很容易进行的。 所以可以想到,加号的耗时应该会比str.join的耗时大很多。当然tmp_tup去引用all_str里的每一个元素,也会消耗一些时间, 之所以加这句代码,是因为加号会比str.join的使用灵活得多,往往要连接的字符串,都不是恰好直接来源于一个tuple。 关于内存使用,由于输入一样,输出一样,最终消耗的内存应该是一样,当然在执行中,内存占用的波动情况应该是不一样的。
某次真实测试结果是:
time dist:0.717386:0.668515
如上面的预估一样,确实str.join要快,最终内存消耗也是一样。但与预估不一致的是, 使用加号与使用str.join的耗时差距并不大,甚至有时,使用加号还会更快一些。
从python的手册里找到了答案,在cpython的实现里,2.4以前的版本里,字符串连接绝对不会是in-place拼接, 也就是说确实有大量的再分配再拷贝的操作,而后来版本就做了优化。
很显然使用加号简洁清爽得多,而使用str.join,你得先把字符串都整到一个tuple或者list中去。 而且,python中的加号字符串连接,并不如我们想像中那么糟糕,跟实现版本有关。 当然还是建议遵守最开始提到的三条准则,大量字符串连接时优先使用str.join。