繁体   English   中英

Python比较2列表和2元组用等号

[英]Python Comparing 2 list and 2 tuple with equality sign

最近我在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

那么为什么时间差异从列表的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

等效列表如下:

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 ,它会继续重新计算它。 请参阅问题9685 ,其中更改的修补程序被拒绝,因为它减慢了某些基准测试并且没有加快任何人都能找到的速度。

**不是因为实现有任何固有的东西,而是因为人们经常比较不同长度的列表,但很少使用元组。

答案也在那篇文章中给出:)

这是证明:

>>> 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解释器会在其内存中计算其哈希值。 如果在2个元组之间进行比较,它只是比较哈希值,它知道它们是否相等!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM