私は自分の python をより pythonic にし、コードの短いスニペットのランタイムをいじることに取り組んできました。読みやすさを改善するだけでなく、実行を高速化することも私の目標です。
この例は、これまで読んできたベスト プラクティスと矛盾しているため、自分の思考プロセスのどこに欠陥があるかを知りたいと思っています。
問題は、2 つの等しい長さの文字列のハミング距離を計算することです。たとえば、文字列 'aaab' と 'aaaa' のハミング距離は 1 です。
私が考えることができる最も簡単な実装は次のとおりです。
def hamming_distance_1(s_1, s_2):
dist = 0
for x in range(len(s_1)):
if s_1[x] != s_2[x]: dist += 1
return dist
次に、2 つの「pythonic」実装を作成しました。
def hamming_distance_2(s_1, s_2):
return sum(i.imap(operator.countOf, s_1, s_2))
と
def hamming_distance_3(s_1, s_2):
return sum(i.imap(lambda s: int(s[0]!=s[1]), i.izip(s_1, s_2)))
実行中:
s_1 = (''.join(random.choice('ABCDEFG') for i in range(10000)))
s_2 = (''.join(random.choice('ABCDEFG') for i in range(10000)))
print 'ham_1 ', timeit.timeit('hamming_distance_1(s_1, s_2)', "from __main__ import s_1,s_2, hamming_distance_1",number=1000)
print 'ham_2 ', timeit.timeit('hamming_distance_2(s_1, s_2)', "from __main__ import s_1,s_2, hamming_distance_2",number=1000)
print 'ham_3 ', timeit.timeit('hamming_distance_3(s_1, s_2)', "from __main__ import s_1,s_2, hamming_distance_3",number=1000)
戻る:
ham_1 1.84980392456
ham_2 3.26420593262
ham_3 3.98718094826
ラムダの呼び出しは関数呼び出しとして扱われ、組み込みの operator.countOf の呼び出しよりも遅いため、ham_3 は ham_2 よりも遅く実行されると予想しました。
しかし、ham_1 よりも高速に実行するより Pythonic バージョンを取得する方法を見つけることができなかったことに驚きました。ham_1 が純粋な python の下限であるとは信じがたいです。
誰か考えますか?