好吧,你的一些困惑是,你正在阅读的博客文章是错的。关于多件事。试着忘记你曾经读过它(除了记住网站和作者的名字,以便你以后知道如何避免它们。)
确实,元组是可以清除的,列表不是,但这与它们的相等测试功能无关。并且它确实不正确#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
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,其中一个要更改的修补程序被拒绝,因为它减慢了某些基准测试并且没有加速任何人都能找到的任何内容。
**不是因为实现有任何固有的东西,而是因为人们经常比较不同长度的列表,但很少使用元组。