为什么在Python 2中'' > 0是True?

43

在Python 2.x中:

>>> '' > 0
True

为什么会这样呢?


23
顺便说一下,Python 3.0针对相同的比较会产生TypeError:unorderable types: str() > int() - mjv
相关问题:https://dev59.com/V2Ml5IYBdhLWcg3wc2xp - Mazdak
2个回答

93
允许任意对象进行比较的原始设计动机是为了允许对异构列表进行排序 - 有用的是,这会将所有字符串按字母顺序排在一起,并将所有数字按数字顺序排在一起,尽管哪个块先出现并不由语言保证。例如,这允许在O(N log N)的最坏情况下获得任何列表中的唯一项(甚至包含非可哈希项的列表)。
多年来,这种实用主义安排已经被削弱。第一个裂缝出现在一段时间前,当能够进行复数的排序比较时被取消。突然之间,排序了任何列表的能力消失了:如果列表包含复数,可能还包括其他类型的项,则不再适用。然后,Guido开始普遍不喜欢异构列表,因此开始认为是否可以有用地对这些列表进行排序并不重要...根据他的新思维,这样的列表不应该存在于第一位。虽然他没有做任何禁止它们的事情,但也不倾向于接受任何妥协来支持它们。
请注意,这两个更改都使得“实用性胜过纯粹性”(Zen of Python的项目)稍微偏离了平衡(在复数仍然可以进行排序比较时编写),有点更纯粹,有点不那么实用。
尽管如此,长时间以来允许对两个任意对象进行排序比较(只要它们中没有一个是复数 ;-)),因为在同一时间,Guido开始真正坚持维护强大的向后兼容性(这是一个同时实用和纯粹的转变;-))。
因此,只有在Python 3中,才明确且故意地删除了强大的向后兼容性的限制,以允许一些长期期望但不向后兼容的增强(特别是简化和删除过时的冗余执行某些任务的方法),不同类型的实例的顺序比较成为错误。
因此,这篇历史和哲学论文基本上是真正回答您的“为什么”问题的唯一方式...! :-)

1
也许应该补充一下,虽然语言可能不再具有此功能,但任意列表的排序可以通过自定义比较器轻松完成。如果需要,只需自己编写即可 - 这也是一个非常实用的方法。 - Trilarion
1
注意:在Python 2中,一个复数可以与任何其他对象进行比较,除了另一个复数!complex(1,0)> 'abc'False,但complex(1,0)> complex(0,0)会引发TypeError错误。 - Eric Duminil
2
@EricDuminil 不完全正确 - 复数不能与布尔值、整数或分数进行比较。由于某种原因(可能是疏忽),它们可以与小数进行比较。 - wim
@wim:感谢您的有趣评论。从技术上讲,您是正确的:这是最好的正确方式!由于我们可以将布尔值、整数、分数和浮点数视为复数,因此这几乎是有意义的。但是十进制数也应该在其中。无论如何,这是针对Python2的,随着时间的推移,它变得越来越不相关了。 - Eric Duminil

23

来自https://docs.python.org/2.7/tutorial/datastructures.html#id1

请注意,比较不同类型的对象是合法的。结果是确定性的但是不可预测的:类型按名称排序。因此,列表始终小于字符串,字符串始终小于元组等等[1]。混合数字类型根据它们的数字值进行比较,因此0等于0.0,等等。


7
奇怪,令人耳目一新的是,Python 3.0不再允许这样做了。 - Justin Ethier
2
这并不是整个故事; 例如,5 < ArithmeticError()即使'int' > 'ArithmeticError'ArithmeticError不是数字类型。 - user2357112
1
完整的故事请看这里 - wim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接