文字列結合のパフォーマンス
- Efficient String Concatenation in Python (http://www.skymind.com/~ocrow/python_string/)
2.5.2でテスト。
import time def profile(func): def foo(*a, **k): t = time.time() r = func(*a, **k) print '%s: %g sec elapsed' % (func.__name__, time.time() - t) return r return foo @profile def method1(): out_str = '' for num in xrange(loop_count): out_str += `num` return out_str @profile def method2(): from UserString import MutableString out_str = MutableString() for num in xrange(loop_count): out_str += `num` return out_str @profile def method3(): from array import array char_array = array('c') for num in xrange(loop_count): char_array.fromstring(`num`) return char_array.tostring() @profile def method4(): str_list = [] for num in xrange(loop_count): str_list.append(`num`) return ''.join(str_list) @profile def method5(): from cStringIO import StringIO file_str = StringIO() for num in xrange(loop_count): file_str.write(`num`) return file_str.getvalue() @profile def method6(): return ''.join([`num` for num in xrange(loop_count)]) @profile def method7(): return ''.join(`num` for num in xrange(loop_count)) @profile def method8(): return '%s'*loop_count % tuple(xrange(1, loop_count+1)) loop_count = 1000000 method1() #method2() method3() method4() method5() method6() method7() method8()
実行結果。
method1: 5.283 sec elapsed method3: 5.486 sec elapsed method4: 0.547 sec elapsed method5: 0.625 sec elapsed method6: 0.438 sec elapsed method7: 0.437 sec elapsed method8: 0.454 sec elapsed
method2は時間かかりすぎで時間切れとみなした。「リスト内包表記(ジェネレータ内包表記) + join」が一番速い。短い文字列だと文字列を+演算子で結合する方が早いと思うが、長い文字列の場合はjoinを使用すべきだと思われる。リスト内包表記とジェネレータ内包表記は速度が変わらなかったのは意外だった。文字列フォーマットも意外と速いが、joinには一歩及ばず。
上記の参考サイトでは MutableString が速いとなっていたが、恐らくPythonのバージョンによるものではないだろうか?基本的にパフォーマンスはPythonのバージョンごとに計測しなおすべきだと思う。
3.0で文字列を表示するなら、print(*range(1, loop_count+1), sep='')という処理が速そうな気がする。Python 3.0では文字列フォーマットがかなり強化されたが、どうせだったらRubyやGroovyのような文字列に埋め込む形のやり方にしてほしかった。3.0のformatメソッドはC#っぽい気がするが、なんか中途半端。Pythonの文法ではRubyやGroovyのやり方は表現できないのだろうか?
結論は以下のとおり。
文字列結合は状況に応じて以下の3通りから最適なものを選択すれば良い。但し指針としては、+演算子は文字列が長い場合には遅いので注意が必要。
- +演算子
- join
- フォーマット文字列