I have defined a list as below:
list = [1,3,2,[4,5,6]]
then defined a comparator method as below:
def reverseCom(x,y):
if(x>y):
return -1
elif(x<y):
return 1
else:
return 0
Now I have sorted the list using reverseCom:
list.sort(reverseCom)
print list
Result : [[4, 5, 6], 3, 2, 1]
Though the element [4, 5, 6] is not comparable with other elements of the list. How its not throwing any error ?
Do you can help me to understand that how sort works with the user defined comparator in python ?
This is a Python 2 quirk. In Python 2, numeric and non numeric values are comparable, and numeric values are always considered to be less than the value of container objects:
>>> 1 < [1]
True
>>> 1 < [2]
True
>>> 1558 < [1]
True
>>> 1 < {}
True
when comparing two containers values of different types, on the other hand, it is the name of their type that is taken into consideration:
>>> () < []
False
>>> 'tuple' < 'list'
False
>>> {} < []
True
>>> 'dict' < 'list'
True
This feature, however, has been dropped in Python 3, which made numeric and non-numeric values no longer comparable:
>>> 1 < [1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < list()
EDIT: this next explanation is fully experimentation-based, and I couldn't find sound documentation to back it up. If any one does find it, I'd be glad to read through it.
It appears Python 2 has even more rules when it comes to comparison of user-defined objects/non-container objects.
In this case it appears that numeric values are always greater than non-numeric non-container values.
>>> class A: pass
...
>>> a = A()
>>> 1 > a
True
>>> 2.7 > a
True
Now, when comparing two objects of different, non-numeric, non-container types, it seems that it is their address that is taken into account:
>>> 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
Which is really bananas, if you ask me.
Of course, all that can be changed around if you care to override the __lt__()
and __gt__()
methods inside your class definition, which determine the standard behavior of the <
and >
operators.
Further documentation on how these methods operate can be found here.
Bottomline: avoid comparison between different types as much as you can. The result is really unpredictable, unintuitive and not all that well documented. Also, use Python 3 whenever possible.
Your comparator actually works, i.e., does not throw any error:
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
The reason why it works is, list
instances always bigger than int
instances:
In [12]: [1,2,3] > 5
Out[12]: True
In [13]: ['hello'] > 5
Out[13]: True
In [14]: [] > -1
Out[14]: True
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With