Python 連接字符串應(yīng)優(yōu)先使用 join 而不是 +
簡介
字符串處理在大多數(shù)編程程序語言中都不可避免,字符串的連接也是在編程過程中經(jīng)常需要面對(duì)的問題扮授。 Python中的字符串與其他一些程序語言如C++芳室、Java有一些不同,它為不 可變對(duì)象刹勃。 一旦創(chuàng)建便不能改變渤愁,它的這個(gè)特性直接影響到Python中字符串連接的效率。 我們首先來看常見的兩種字符串連接方法深夯。
使用操作符+連接字符串的方法如下:
strl, str2, str3 =“testing”, “string”,“concatenation”
strl + str2 + str3
‘testingstringconcatenation’
3.9.2. 使用join方法連接字符串的方法如下:
‘’.join ([strl, str2, str3])
‘testingstringconcatenation’
思考這么一個(gè)問題:上述兩種字符串連接的方法除了使用形式上的不同還有其他區(qū)別 嗚?性能上會(huì)不會(huì)有所差異呢诺苹?來看下面這個(gè)測(cè)試?yán)樱?/p>
import timeit
#生成塒試所雋要的字符數(shù)組
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):
#使用*進(jìn)行宇符串連接
result=(result + v)
return result
現(xiàn)在開始測(cè)試:
jointimer = timeit.Timer(“join_test()” ,“from main import join_test”)
print (jointimer.timeit(number = 100))
0.11032061399964732
第二種方式:
plustimer = timeit.Timer (“plus_test()”,“from main import plus_test”)
print( plustimer.timeit(number = 100))
1.025606508999772
給上曲的程序傳入一組測(cè)試參數(shù)(測(cè)試參數(shù)為3, 10,100咕晋,1000,10000, 100000; 分 別表示每一次測(cè)試所要連接的字符串的數(shù)量X程序用于測(cè)試 join_test() 和 plus_test() 這兩個(gè)方法在宇符串連接規(guī)模改變時(shí)所消耗時(shí)間的變化收奔。
從分析測(cè)試結(jié)果圖表我們不難發(fā)現(xiàn):分別使用join方法和使用+操作符來連接字符串. join()方法的效率要高于+操作符掌呜,特別是字符串規(guī)模較大的時(shí)候,join()方法的優(yōu)勢(shì)更為明顯(如連接數(shù)為100000的時(shí)候坪哄,兩者耗時(shí)相差上百倍)质蕉。造成這種差別的原因在哪里呢?我們來探討一下翩肌。當(dāng)用操作符+連接字符串的時(shí)候.由于字符串是不可變對(duì)象.其工作原理實(shí)際上是這樣的:如果要連接如下字符串:S1+S2+S3+…….+SN模暗,執(zhí)行一次+操作便會(huì)在內(nèi)存中申請(qǐng)一塊新的內(nèi)存空間,并將上一次操 作的結(jié)果和本次操作的右操作數(shù)復(fù)制到新 申請(qǐng)的內(nèi)存空間念祭,即當(dāng)執(zhí)行SI+S2的時(shí)候 會(huì)申請(qǐng)一塊內(nèi)存兑宇,并將SI、S2復(fù)制到該內(nèi) 存屮.依次類推粱坤。
因此.在 N個(gè)字符串連接的過程中隶糕,會(huì)產(chǎn)生N-I個(gè) 中間結(jié)果,每產(chǎn)生一個(gè)中間結(jié)果都需要申 請(qǐng)和復(fù)制一次內(nèi)存站玄,總共需要申請(qǐng)N-1次 內(nèi)存枚驻,從而嚴(yán)童影響了執(zhí)行效率。N越大株旷,
對(duì)內(nèi)存的申請(qǐng)和復(fù)制的次數(shù)越多再登,+操作符的效率就越低。因此.整個(gè)字符連接的過程中灾常, 相當(dāng)于S1被復(fù)制N-1次霎冯,S2被復(fù)制N-2次….SN復(fù)制1次(并不完全等同于S1復(fù)制N-1 次,因?yàn)楹罄m(xù)復(fù)制都是對(duì)中間結(jié)果的復(fù)制所以字符串的連接時(shí)間復(fù)雜度近似為O(n^2)钞瀑。 而當(dāng)用 join() 方法連接字符串請(qǐng)的總的內(nèi)存空間沈撞,然后一次 性申請(qǐng)所需內(nèi)存并將字符序列中的每一個(gè)元素復(fù)制到內(nèi)存中去, 所以 join 操作的時(shí)間復(fù)雜度 為 O(n)
因此雕什,宇符串的連接缠俺,特別是大規(guī)模字符串的處理显晶,應(yīng)該盡量優(yōu)先使用 join 而不是 + 。