比较不相关的类型
介绍
>>> x = range(50)
>>> x < 20
x < 20的值是多少?
我会为你消除悬念,这是假的。
我知道,这对我来说也没有意义。我不知道将整数与列表进行比较在语义上意味着什么,但我想知道为什么 Python 将这种比较转换为False。
我认为这个答案可能与即将进行的演讲有关。毕竟,<运算符的实现是由列表类型的小于 dunder 方法处理的。
假设
我的第一个想法是,<运算符正在与列表的len()进行比较,这会导致x < 51 True。结果:错误。
也许 Python 使用的是列表的id。这在某种程度上是有道理的,因为每个对象都有一个唯一的 Long ID —— 一个理想的比较工具。结果:错误。
>>> id(x)
170461900
>>> x < 170461901
False
回到源头!
此时,这个谜团促使我下载了Python 2.7源代码。
我本可以搜索互联网来寻找快速解决方案,但我想花一点时间深入研究Python 2.7源代码。
我开始在列表对象中查找 '<' 的实现。这就是跟踪C函数指针和宏的乐趣开始的时候……
我将节省您的时间,仅提供我发现的内容的摘要。比较操作在default_3way_compare函数中结束。
以下代码片段通过确定我们的列表始终大于(而不是小于)所有整数来决定所有列表整数比较的结果:
/* different type: compare type names; numbers are smaller */
if (PyNumber_Check(v))
vname = "";
else
vname = v->ob_type->tp_name;
if (PyNumber_Check(w))
wname = "";
else
wname = w->ob_type->tp_name;
c = strcmp(vname, wname);
if (c < 0)
return -1;
if (c > 0)
return 1;
惊讶?困惑?我两者都有。
惊喜!
经过进一步的研究,我发现比较是基于类型的实际名称!因此,在我们的例子中,List 的字母顺序大于Integer!这种模式在大多数类型比较中都存在。
这并不是我所希望的理由,但至少我们有一个答案。
不过,既然我们知道发生了什么,看看你是否能找出更多谜题的答案:
>>> [] < ()
>>> [] < {}
剧透警告
List小于Tuple ,记住字母表中 'L' 位于' T' 之前,当然按照同样的逻辑 List不小于Dict。
复活节彩蛋
相比之下,没有一个是真正 小的:
/* None is smaller than anything */
if (v == Py_None)
return -1;
if (w == Py_None)
return 1;
Python 3
到目前为止,我一直在使用 Python 2.7。我想知道在这种情况下Python 3会做什么。
>>> x = range(50)
>>> x < 20
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: range() < int()
>>> [] < ()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: list() < tuple()
>>> [] < {}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: list() < dict()
太棒了!如上所示,不相关的类型比较现在会导致 TypeError,这个结果比字母顺序更容易理解。所以这个小问题已经修复了。
当你将你出色的应用程序升级到Python 3时,比较完全不同的类型会导致解释器大声抱怨,这是应该的。然后,你就可以忘记你在本篇文章中学到的一切了。:)
建议阅读
如果你感兴趣的话,在我完成挖掘后,我发现了一篇很棒的stackoverflow 帖子,证实了上述所有研究。你也可以查看 Python文档来找到相同的答案。尽管如此,浏览 Python 源代码还是一次很有启发的经历。
附注:此实现是CPython的实现选择。使用其他 Python 实现(如pypy)的结果可能会有所不同。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~