比较器如何处理python中无法比较的对象?

时间:2015-12-26 19:33:30

标签: python

我已经定义了一个列表如下:

list = [1,3,2,[4,5,6]]

然后定义了一个比较方法如下:

def reverseCom(x,y):
   if(x>y):
        return -1
   elif(x<y):
        return 1
   else:
        return 0

现在我使用reverseCom对列表进行了排序:

list.sort(reverseCom)
print list
  

结果:[[4,5,6],3,2,1]

虽然元素[4,5,6]与列表中的其他元素不具有可比性。怎么不抛出任何错误?

你能帮我理解python中用户定义的比较器的排序方式吗?

2 个答案:

答案 0 :(得分:10)

这是Python 2的怪癖。在Python 2中,数值和非数值是可比较的,并且数值始终被认为小于容器对象的值:

>>> 1 < [1]
True
>>> 1 < [2]
True
>>> 1558 < [1]
True
>>> 1 < {}
True

比较两个不同类型的容器值时,另一方面,考虑到类型的名称

>>> () < []
False
>>> 'tuple' < 'list'
False

>>> {} < []
True
>>> 'dict' < 'list'
True

然而,此功能已在Python 3中删除,这使得数字和非数字值不再具有可比性:

>>> 1 < [1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < list()

编辑:下一个解释是完全基于实验的,我无法找到合理的文档进行备份。如果有人找到它,我很乐意通读它。

在比较用户定义的对象/非容器对象时,Python 2似乎有更多的规则。

在这种情况下,数值似乎总是更大而不是非数字非容器值。

>>> class A: pass
...
>>> a = A()
>>> 1 > a
True
>>> 2.7 > a
True

现在,在比较不同的非数字非容器类型的两个对象时,似乎考虑了它们的地址

>>> class A: pass
...
>>> class B: pass
...
>>> a = A()
>>> a
<__main__.A instance at 0x0000000002265348>
>>> b = B()
>>> b
<__main__.B instance at 0x0000000002265048>
>>> a < b
False
>>> b < a
True

如果你问我,那真的是香蕉。

当然,如果您想覆盖类定义中的__lt__()__gt__()方法,那么可以改变所有这些方法,这些方法决定了<和{{的标准行为1}}运营商。

有关这些方法如何运作的进一步文档可以是found here

底线:尽量避免在不同类型之间进行比较。结果实际上是不可预测的,不直观的,并没有充分记录。另外,尽可能使用Python 3。

答案 1 :(得分:1)

您的比较器确实有效,即不会抛出任何错误:

In [9]: reverseCom([4,5,6],1)
Out[9]: -1

In [10]: reverseCom([4,5,6],2)
Out[10]: -1

In [11]: reverseCom([4,5,6],3)
Out[11]: -1

它起作用的原因是list个实例总是大于int个实例:

In [12]: [1,2,3] > 5
Out[12]: True

In [13]: ['hello'] > 5
Out[13]: True

In [14]: [] > -1
Out[14]: True