Я работал над тем, чтобы сделать свой питон более питоническим и экспериментировать со средами выполнения коротких фрагментов кода. Моя цель улучшить читаемость, но, кроме того, ускорить выполнение.
Этот пример противоречит лучшим практикам, о которых я читал, и мне интересно выяснить, в чем недостаток моего мыслительного процесса.
Проблема состоит в том, чтобы вычислить расстояние Хэмминга для двух строк равной длины. Например, расстояние хэмминга для строк «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
Затем я написал две «питонические» реализации:
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
Я ожидал, что ham_3 будет работать медленнее, чем ham_2, из-за того, что вызов лямбды обрабатывается как вызов функции, что медленнее, чем вызов встроенного operator.countOf.
Я был удивлен, что не смог найти способ заставить более питоническую версию работать быстрее, чем ham_1. Мне трудно поверить, что ham_1 - это нижняя граница для чистого питона.
Кто-нибудь думает?