2010年11月5日金曜日

pythonの文字列編集

いちおう、個人的な結論が出ました:
 普通のサイズなら+=で十分。listを育てて''.join(list)するのはナンセンス。
 多少大きいなら、''.join([i for i in ジェネレータ])
 本当に大きいなら、''.join(ジェネレータ)

ジェネレータをリスト内包表記でリストにしたほうが たいてい 速いというのは、意外な結果でした。

以下が検証につかったプログラムです。

from timeit import Timer

#リストを育てて、join
str_test1 = """
for num in _gen:
    str_list.append(num)
_join(str_list)
"""

#stringIOに追記
str_test2 = """
for num in _gen:
    file_str.write(num)
file_str.getvalue()
"""

#charのarrayに追加
str_test3 = """
for num in _gen:
    char_array.fromstring(num)
char_array
"""

# += で 育てていく
str_test4 = """
for num in _gen:
    out_str += num
out_str
"""

# リスト内包表記をjoin
str_test5 = """
ret = _join([i for i in _gen])
ret
"""

# ジェネレータを直にjoin
str_test6 = """
ret = _join(_gen)
ret
"""

setup = """
loop_count = 30
out_str = ''
from array import array
char_array = array('c') 
str_list = []
from cStringIO import StringIO
file_str = StringIO()
_join = ''.join
_name = 'test'
_gen=('<test' + ' name="' + _name + '"' + '>' + `num` + '</test>' for num in xrange(loop_count))
"""

print Timer(str_test1, setup).repeat(3, 100)
print Timer(str_test2, setup).repeat(3, 100)
print Timer(str_test3, setup).repeat(3, 100)
print Timer(str_test4, setup).repeat(3, 100)
print Timer(str_test5, setup).repeat(3, 100)
print Timer(str_test6, setup).repeat(3, 100)


loop_count=30
[0.00024053336528595537, 0.00023634288663743064, 0.00023606352260685526]
[0.00015420954332512338, 0.0001477841469750274, 0.00015532700490439311]
[8.7441281721112318e-005, 8.353016892215237e-005, 8.2692073192447424e-005]
[7.2076200012816116e-005, 6.7326993303140625e-005, 6.7885723183280788e-005]
[8.0177787822321989e-005, 7.5987310992786661e-005, 7.5707945143221878e-005]
[0.00047128894948400557, 0.00047352387082355563, 0.00047156831351458095]


# +=が一番速い!
# ''.join(ジェネレータ)は一番遅い!


loop_count=300
[0.0019653335821203655, 0.0020566859766404377, 0.0019753907254198566]
[0.00092833027701999526, 0.00092358107031031977, 0.00092413980019045994]
[0.00075568263673631009, 0.00067997468977409881, 0.00062019055440032389]
[0.00051794292267004494, 0.00050229847693117335, 0.00050257784096174873]
[0.00045676196350541431, 0.00043832386472786311, 0.00044111751776654273]
[0.00082524454956001136, 0.00080149851419264451, 0.0007970286733325338]
# ''.join(i for i in ジェネレータ)の順位が上昇。一番速い!
# ''.join(ジェネレータ)の順位が上昇。


loop_count=3000
[0.024607876141089946, 0.024106695123919053, 0.023980701458640397]
[0.017470097456680378, 0.019163050053975894, 0.021411380497738719]
[0.009339734519016929, 0.0092833027665619738, 0.0093380583293765085]
[0.0081722677041398128, 0.0050972958852071315, 0.0080621978486306034]
[0.0041698037039168412, 0.0040753782959654927, 0.0040725846429268131]
[0.0043092068972327979, 0.004270654510037275, 0.0042558481600281084]
# ''.join(ジェネレータ)が2位に。


loop_count=30000
[0.32366962840205815, 0.33386114715540316, 0.33299315974545607]
[0.19254905302113912, 0.19246356729672698, 0.19229231648205314]
[0.18879075413315149, 0.14344420869201713, 0.18765234128841257]
[0.13475986473167723, 0.16792050386175106, 0.1337812487345218]
[0.054552184705244144, 0.055729149933540612, 0.055441683231038041]
[0.046381872556594317, 0.05237118125478446, 0.052848616234768997]
# ''.join(ジェネレータ)が1位に。
#  でも、''.join(i for i in ジェネレータ)とあんまり変わらない。なぜに?


loop_count=300000
[3.215461741645413, 3.1868516808699496, 3.1819172548475763]
[2.0470207805756218, 2.0494777967596747, 2.0539613274868316]
[16.015020065398858, 16.072113355188776, 16.03753214444987]
[15.98263103271529, 15.960840553758317, 15.985554309276267]
[0.47812361627075006, 0.46673641482448147, 0.48726667774826637]
[0.46456016057891247, 0.45079220962543332, 0.46201709993874829]
# += と char_array が、一番遅くなった。

0 件のコメント:

コメントを投稿