Sha*_*rma 2 python hash tuples list python-3.x
最近我在Python中学习了更多关于哈希的知识,我在这个博客中说到:
假设一个Python程序有2个列表.如果我们需要考虑比较这两个列表,你会怎么做?比较每个元素?嗯,这听起来很简单,但也很慢!
Python有一个更聪明的方法来做到这一点.当在程序中构造元组时,Python解释器会在其内存中计算其哈希值.如果在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
Run Code Online (Sandbox Code Playgroud)
那么为什么从0.14
列表到0.03
元组的时间差异比列表更快.
好吧,你的一些困惑是,你正在阅读的博客文章是错的.关于多件事.试着忘记你曾经读过它(除了记住网站和作者的名字,所以你知道将来要避免它们).
确实,元组是可清除的,列表不是,但这与它们的相等测试函数无关.并且它肯定不是"它只是比较哈希值,它知道它们是否相等!" 哈希碰撞发生,忽略它们会导致可怕的错误,幸运的是Python的开发人员并不是那么愚蠢.实际上,Python在初始化时计算哈希值并不是真的.*
实际上有是元组和列表之间的一个显著的差异(在CPython的,如3.6),但它通常不会太大的差别:列出一开始作为优化做长度不等额外的检查,但相同的检查横空出世对元组来说是一种悲观,**所以它从那里被删除了.
另一个,通常更为重要的区别是,源中的元组文字被编译为常量值,同一元组文字的单独副本被折叠到同一个常量对象中; 由于显而易见的原因,列表不会发生这种情况.
事实上,这就是你真正用你的测试timeit
.在我的笔记本电脑上,比较元组需要95ns,而比较列表需要169ns - 但是将其分解,实际上比较为93ns,另外还有38ns来创建每个列表.为了使其公平比较,您必须将创建移动到设置步骤,然后比较循环内已存在的值.(或者,当然了,你可能不希望是公平的-你发现,每次使用一个元组常量,而不是创建一个新的列表的时候,你节省一微秒的显著部分有用的事实.)
除此之外,他们基本上做同样的事情.翻译C源成Python类伪(和删除所有的错误处理,这使得相同功能工作的东西<
,等等):
for i in range(min(len(v), len(w))):
if v[i] != w[i]:
break
else:
return len(v) == len(w)
return False
Run Code Online (Sandbox Code Playgroud)
该列表相当于是这样的:
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
Run Code Online (Sandbox Code Playgroud)
*实际上,与字符串不同,元组甚至不会缓存它们的哈希值; 如果你hash
反复打电话,它会继续重新计算它.请参阅问题9685,其中更改的修补程序被拒绝,因为它减慢了某些基准测试并且没有加快任何人都能找到的速度.
**不是因为实现有任何固有的东西,而是因为人们经常比较不同长度的列表,但很少使用元组.
归档时间: |
|
查看次数: |
569 次 |
最近记录: |