strl, str2, str3 ="testing", "string","concatenation"
strl + str2 + str3
'testingstringconcatenation'
''.join ([strl, str2, str3])
'testingstringconcatenation'
思考这么一个问题:上述两种字符串连接的方法除了使用形式上的不同还有其他区别呜? 性能上会不会有所差异呢?来看下面这个测试例子:
import timeit
生成埘试所雋要的字符數组
strlist=["it is a long value string will not keep in memory" for n in range(100000)]
def join_test():
#使用join方法连接strlist中的元#并返回字符串
return ' ' . join (strlist)
def plus_test():
result =""
for i,v in enumerate(strlist):
#使用*进行宇符串连接
result=(result + v)
return result
现在开始测试:
jointimer = timeit.Timer("join_test()" ,"from __main__ import join_test")
print (jointimer.timeit(number = 100))
0.13505697700020391
第二种方式:
plustimer = timeit.Timer ("plus_test()","from __main__ import plus_test")
print( plustimer.timeit(number = 100))
2.1114536239983863
给上曲的程序传入一组测试参数(测试参数为3, 10,100,1000,10000, 100000; 分
别表示每一次测试所要连接的字符串的数量X程序用于测试 join_test()
和 plus_test()
这两个方法在宇符串连接规模改变时所消耗时间的变化。
测试结果记录如表所示
下图所示的X.Y图表示,其中X轴表示所要连接的字符串的数量,Y轴表示消耗的时间。
从分析测试结果图表不难发现:
分别使用 join
方法和使用 +
操作符来连接字符串. join()
方法的效率要高于 +
操作符,
特別是字符串规模较大的时候,join()
方法的优势更为明显(如连接数为100000的时候,两者耗时相差上百倍)。
造成这种差别的原因在哪里呢?探讨一下。当用操作符+连接字符串的时候.由于字符串是不可变对象.其工作原理实际上是这样的:
如果要连接如下字符串: S1+S2+S3+.......+SN
,执行一次+操作便会在内存中申请一块新的内存空间,
并将上一次操 作的结果和本次操作的右操作数复制到新 申请的内存空间,即当执行SI+S2的时候会申请一块内存,
并将 SI
、 S2
复制到该内存中,依次类推,如图:
因此,在 N
个字符串连接的过程中,会产生 N-I
个中间结果,每产生一个中间结果都需要申请和复制一次内存,
总共需要申请 N-1
次内存,从而严童影响了执行效率。 N
越大,对内存的申请和复制的次数越多,
+
操作符的效率就越低。因此.整个字符连接的过程中,
相当于S1被复制 N-1
次, S2
被复制 N-2
次 ....SN
复制1次(并不完全等同于S1复制 N-1
次,
因为后续复制都是对中间结果的复制所以字符串的连接时间复杂度近似为O(n^2)。
而当用 join()
方法连接字符串请的总的内存空间,
然后一次 性申请所需内存并将字符序列中的每一个元素复制到内存中去,
所以 join
操作的时间复杂度 为 O(n)
因此,宇符串的连接,特别是大规模字符串的处理,应该尽量优先使用 join
而不是 +
。