在Python 2中,有可能通过隐式比较类型的文本字符串(即,按字典顺序排列,字符串int
小于字符串str
和字符串'int'
小于)来比较不同类型的对象,如'str'
和'list'
。 string 'tuple'
)。
因此,在Python 2中,5 < 'hello'
返回True
。人们可以阅读更多关于为什么允许回答Why is ''>0 True in Python?的原因。
在Python 3中,这引发了builtins.TypeError: unorderable types: int() < str()
异常。
这web page说
在Python 3中进行比较的严格方法使得通常无法比较不同类型的对象。
这是否意味着有一些内置类型或特殊情况可以比较任何内置类型而不会导致TypeError
?我不是在谈论自定义类型,其中实现了必要的dunder方法以正确支持比较。
所有这些都是有效的陈述(它们都评估为True
):
0 < True
0 < 1.
0. < True
{0} < frozenset((0, 1))
唯一可能看起来奇怪的是0. == False
和1. == True
。
另一方面,你仍然可以通过在比较它之前将你的值转换为str
来重现python 2的作用(这也评估为True
):
str(5) < 'hello'
如果你真的需要这种行为,你可以随时拥有一个将进行强制转换/比较的函数。这样你就可以保证不同类型的对象总是以相同的方式进行比较,这似乎是python 2中唯一的约束。
def lt(a, b):
return str(a) < str(b)
或者甚至更好,你可以只在需要时施放:
def lt(a, b):
try:
return a < b
except TypeError:
return str(a) < str(b)
另一方面,正如评论中所建议的那样,在CPython的实现中,似乎比较是通过以下方式完成的:
def lt(a, b):
try:
return a < b
except TypeError:
if a is None:
return True
if b is None:
return False
if isinstance(a, numbers.Number):
return True
if isinstance(b, numbers.Number):
return False
return str(type(a)) < str(type(b))
我之前已经在网上看过这个了,除了上面提到的几个特殊情况外,它们在Python 3中看起来确实不合算。
这种变化通常表现在排序列表中:在Python 3中,包含不同类型项目的列表通常不可排序。如果需要对异构列表进行排序或比较不同类型的对象,请实现一个关键功能,以完整地描述应该如何排序不同类型。 Source
我不知道为什么,但有些人找到了使用Python 3重现Python 2行为的方法。
也许你应该看看this或that。 This question还强调了2011年的变化:
找到它:埋在PEP 3100中:“不同类型之间的==和!=之外的比较将引发异常,除非明确支持类型”