文字列の連結に+を使用してはならず、代わりに常に''.joinを使用するという仮定は神話かもしれません。を使用+
すると、不変の文字列オブジェクトの不要な一時コピーが作成されることは事実ですが、他のよく引用されない事実はjoin
、ループで呼び出すと、通常、のオーバーヘッドが追加されることですfunction call
。あなたの例を見てみましょう。
2つのリストを作成します。1つはリンクされたSOの質問からのもので、もう1つはより大きな作成されたものです。
>>> myl1 = ['A','B','C','D','E','F']
>>> myl2=[chr(random.randint(65,90)) for i in range(0,10000)]
2つの関数を作成し、それぞれと機能を使用してみUseJoin
ましょう。UsePlus
join
+
>>> def UsePlus():
return [myl[i] + myl[i + 1] for i in range(0,len(myl), 2)]
>>> def UseJoin():
[''.join((myl[i],myl[i + 1])) for i in range(0,len(myl), 2)]
最初のリストでtimeitを実行しましょう
>>> myl=myl1
>>> t1=timeit.Timer("UsePlus()","from __main__ import UsePlus")
>>> t2=timeit.Timer("UseJoin()","from __main__ import UseJoin")
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=100000)/100000)
2.48 usec/pass
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000)
2.61 usec/pass
>>>
実行時間はほぼ同じです。
cProfileを使用しましょう
>>> myl=myl2
>>> cProfile.run("UsePlus()")
5 function calls in 0.001 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.001 0.001 0.001 0.001 <pyshell#1376>:1(UsePlus)
1 0.000 0.000 0.001 0.001 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {len}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {range}
>>> cProfile.run("UseJoin()")
5005 function calls in 0.029 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.015 0.015 0.029 0.029 <pyshell#1388>:1(UseJoin)
1 0.000 0.000 0.029 0.029 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {len}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
5000 0.014 0.000 0.014 0.000 {method 'join' of 'str' objects}
1 0.000 0.000 0.000 0.000 {range}
また、Joinを使用すると、オーバーヘッドが増える可能性のある不要な関数呼び出しが発生するようです。
さて、質問に戻ります。すべての場合に+
overの使用を思いとどまらせる必要がありますか?join
いいえ、物事を考慮に入れる必要があると思います
- 問題の文字列の長さ
- 連結操作はありません。
そして、開発の時期尚早な最適化のコース外は悪です。