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

Ari*_*jit 7 python

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

list = [1,3,2,[4,5,6]]
Run Code Online (Sandbox Code Playgroud)

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

def reverseCom(x,y):
   if(x>y):
        return -1
   elif(x<y):
        return 1
   else:
        return 0
Run Code Online (Sandbox Code Playgroud)

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

list.sort(reverseCom)
print list
Run Code Online (Sandbox Code Playgroud)

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

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

你能帮助我理解python中用户定义的比较器的排序是如何工作的吗?

zay*_*ora 10

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

>>> 1 < [1]
True
>>> 1 < [2]
True
>>> 1558 < [1]
True
>>> 1 < {}
True
Run Code Online (Sandbox Code Playgroud)

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

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

>>> {} < []
True
>>> 'dict' < 'list'
True
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

在这种情况下,似乎数值始终大于非数字非容器值.

>>> class A: pass
...
>>> a = A()
>>> 1 > a
True
>>> 2.7 > a
True
Run Code Online (Sandbox Code Playgroud)

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

>>> 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
Run Code Online (Sandbox Code Playgroud)

如果你问我,这真的是香蕉.

当然,如果你想覆盖类定义中的__lt__()__gt__()方法,那么所有这些都可以改变,这决定了<>运算符的标准行为.

有关这些方法如何运作的进一步文档可以在这里找到.

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


Sai*_*ait 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
Run Code Online (Sandbox Code Playgroud)

它起作用的原因是,list实例总是比int实例大:

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

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

In [14]: [] > -1
Out[14]: True
Run Code Online (Sandbox Code Playgroud)