用python解释汉明距离速度
我一直在努力使我的python更具python风格,并在运行时玩弄一些简短的代码片段。我的目标是提高可读性,但另外,加快执行速度 这个例子与我一直在阅读的最佳实践相冲突,我想找出我的思维过程中的缺陷所在 问题是计算两个等长字符串上的值。例如,字符串“aaab”和“aaaa”的汉明距离为1 我能想到的最直接的实现如下:用python解释汉明距离速度,python,runtime,timeit,hamming-distance,Python,Runtime,Timeit,Hamming Distance,我一直在努力使我的python更具python风格,并在运行时玩弄一些简短的代码片段。我的目标是提高可读性,但另外,加快执行速度 这个例子与我一直在阅读的最佳实践相冲突,我想找出我的思维过程中的缺陷所在 问题是计算两个等长字符串上的值。例如,字符串“aaab”和“aaaa”的汉明距离为1 我能想到的最直接的实现如下: def hamming_distance_1(s_1, s_2): dist = 0 for x in range(len(s_1)): if s_
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
接下来,我编写了两个“pythonic”实现:
def hamming_distance_2(s_1, s_2):
return sum(i.imap(operator.countOf, 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慢,因为调用lambda被视为函数调用,这比调用内置操作符.countOf慢
我很惊讶,我没能找到一个比ham_1运行得更快的Python版本。我很难相信ham_1是纯python的下限
有人认为吗?关键是减少方法查找和函数调用:
def hamming_distance_4(s_1, s_2):
return sum(i != j for i, j in i.izip(s_1, s_2))
在我的系统中以ham_4 1.10134792328运行
ham_2
和ham_3
在循环内部进行查找,因此它们的速度较慢。我想知道从更广泛的意义上讲,这是否更像python。如果你用。。。一个已经实现了您想要的功能的模块?我想说,只有您的第一个实现是“Pythonic”的。最终,这是一个时间最快的解决方案,sum(I.imap(operator.ne,s_1,s_2))在1.03中运行。是的,就是这样。谢谢ham_4大约在1.67991399765中运行以进行比较。我被ham_2的缓慢程度弄糊涂了,在进一步挖掘之后,我意识到operator.countOf在字符串(每个长度为1)上运行一个for循环,编译器没有对此进行优化。Using operator.ne没有for循环,运行时间为上述示例的1/2。OP要求对字符串数组进行汉明距离计算,而不是int。Scipy空间距离计算仅适用于整数。
def hamming_distance_4(s_1, s_2):
return sum(i != j for i, j in i.izip(s_1, s_2))