我已经定义了一个列表如下:
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中用户定义的比较器的排序方式吗?
答案 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