最近我一直在学习更多关于Python中的哈希的知识,我来到了blog,它说明了:
假设Python程序有2个列表。如果我们需要考虑 比较这两个清单,你会做什么?比较每个元素? 嗯,这听起来很简单,但也很慢!
Python有一个更聪明的方法来做到这一点。构造元组时 在程序中,Python Interpreter在其内存中计算其哈希值。如果 在2个元组之间进行比较,它只是比较哈希 价值,它知道它们是否相等!
所以我对这些陈述感到很困惑。
首先我们这样做:
[1, 2, 3] == [1, 2, 3]
那么这种平等如何运作?它是否计算哈希值然后进行比较?
我们做的第二个区别是什么:
[1, 2, 3] == [1, 2, 3]
和(1, 2, 3) == (1, 2, 3)
?
因为当我试图用timeit找到执行时间时,我得到了这个结果:
$ python3.5 -m timeit '[1, 2, 3] == [1, 2, 3]'
10000000 loops, best of 3: 0.14 usec per loop
$ python3.5 -m timeit '(1, 2, 3) == (1, 2, 3)'
10000000 loops, best of 3: 0.0301 usec per loop
那么为什么从列表的0.14
到列表的0.03
的时间差异比列表更快。
答案 0 :(得分:7)
好吧,你的一些困惑是,你正在阅读的博客文章是错的。关于多件事。试着忘记你曾经读过它(除了记住网站和作者的名字,以便你以后知道如何避免它们。)
确实,元组是可以清除的,列表不是,但这与它们的相等测试功能无关。并且它确实不正确#34;它只是比较哈希值,它知道它们是否相等!"哈希碰撞发生,忽略它们会导致可怕的错误,幸运的是,Python的开发人员并不是那么愚蠢。事实上,Python在初始化时计算哈希值是不正确的。 *
实际上是元组和列表之间的一个显着差异(在CPython中,从3.6开始),但它通常没有太大区别:列表对不等长度进行额外检查作为优化的开始,但同样的检查结果是元组的悲观, ** 所以它从那里被删除。
另一个,通常更为重要的区别是,源中的元组文字被编译为常量值,同一元组文字的单独副本被折叠到同一个常量对象中;由于显而易见的原因,列表不会发生这种情况。
事实上,这就是您使用timeit
进行真正测试的内容。在我的笔记本电脑上,比较元组需要95ns,而比较列表需要169ns - 但是将其分解,实际上比较为93ns,另外还有38ns来创建每个列表。为了使其公平比较,您必须将创建移动到设置步骤,然后比较循环内已存在的值。 (或者,当然,你可能不希望公平 - 你发现了一个有用的事实,即你每次使用元组常量而不是创建一个新列表时,你都会这样做节省了相当大的一微秒。)
除此之外,他们基本上做同样的事情。将the C source转换为类似Python的伪代码(并删除所有错误处理,以及使<
使相同功能起作用的内容,等等):
for i in range(min(len(v), len(w))):
if v[i] != w[i]:
break
else:
return len(v) == len(w)
return False
list equivalent是这样的:
if len(v) != len(w):
return False
for i in range(min(len(v), len(w))):
if v[i] != w[i]:
break
else:
return True
return False
*事实上,与字符串不同,元组甚至不会缓存它们的哈希值;如果你反复拨打hash
,它会继续重新计算它。请参阅issue 9685,其中一个要更改的修补程序被拒绝,因为它减慢了某些基准测试并且没有加速任何人都能找到的任何内容。
**不是因为实现有任何固有的东西,而是因为人们经常比较不同长度的列表,但很少使用元组。
答案 1 :(得分:0)
该文章也给出了答案:)
这里是演示:
>>> l1=[1,2,3]
>>> l2=[1,2,3]
>>>
>>> hash(l1) #since list is not hashable
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> t=(1,2,3)
>>> t2=(1,2,3)
>>> hash(t)
2528502973977326415
>>> hash(t2)
2528502973977326415
>>>
在上面当你在列表上调用hash时它会给你TypeError,因为它不可以和两个列表python相等,检查它的内部值会导致花费很多时间
在元组的情况下,它计算哈希值和两个具有相同哈希值的类似元组,因此python只比较元组的哈希值,所以它比列表快得多
来自给定的文章
Python有一个更聪明的方法来做到这一点。构造元组时 在程序中,Python Interpreter在其内存中计算其哈希值。如果 在2个元组之间进行比较,它只是比较哈希 价值,它知道它们是否相等!