用python解释汉明距离速度

用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_

我一直在努力使我的python更具python风格,并在运行时玩弄一些简短的代码片段。我的目标是提高可读性,但另外,加快执行速度

这个例子与我一直在阅读的最佳实践相冲突,我想找出我的思维过程中的缺陷所在

问题是计算两个等长字符串上的值。例如,字符串“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
接下来,我编写了两个“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))