cmp was removed because the key attribute to . sort() and sorted() is superior in most cases. It was a hold-over from C more than anything, and was confusing to boot. Having to implement a separate __cmp__ method next to the rich comparison operators ( __lt__ , __gt__ , etc.)
cmp() does not work in python 3. You might want to see list comparison in Python. Practical Application: Program to check if a number is even or odd using cmp function. Approach: Compare 0 and n%2, if it returns 0, then it is even, else its odd.
The __cmp__() special method is no longer honored in Python 3. In Python 2, __cmp__(self, other) implemented comparison between two objects, returning a negative value if self < other , positive if self > other , and zero if they were equal.
Python - cmp() Method The cmp() is part of the python standard library which compares two integers. The result of comparison is -1 if the first integer is smaller than second and 1 if the first integer is greater than the second. If both are equal the result of cmp() is zero.
You need to provide the rich comparison methods for ordering in Python 3, which are __lt__
, __gt__
, __le__
, __ge__
, __eq__
, and __ne__
. See also: PEP 207 -- Rich Comparisons.
__cmp__
is no longer used.
More specifically, __lt__
takes self
and other
as arguments, and needs to return whether self
is less than other
. For example:
class Point(object):
...
def __lt__(self, other):
return ((self.x < other.x) and (self.y < other.y))
(This isn't a sensible comparison implementation, but it's hard to tell what you were going for.)
So if you have the following situation:
p1 = Point(1, 2)
p2 = Point(3, 4)
p1 < p2
This will be equivalent to:
p1.__lt__(p2)
which would return True
.
__eq__
would return True
if the points are equal and False
otherwise. The other methods work analogously.
If you use the functools.total_ordering
decorator, you only need to implement e.g. the __lt__
and __eq__
methods:
from functools import total_ordering
@total_ordering
class Point(object):
def __lt__(self, other):
...
def __eq__(self, other):
...
This was a major and deliberate change in Python 3. See here for more details.
- The ordering comparison operators (
<
,<=
,>=
,>
) raise aTypeError
exception when the operands don’t have a meaningful natural ordering. Thus, expressions like1 < ''
,0 > None
orlen <= len
are no longer valid, and e.g.None < None
raisesTypeError
instead of returningFalse
. A corollary is that sorting a heterogeneous list no longer makes sense – all the elements must be comparable to each other. Note that this does not apply to the==
and!=
operators: objects of different incomparable types always compare unequal to each other.builtin.sorted()
andlist.sort()
no longer accept thecmp
argument providing a comparison function. Use thekey
argument instead. N.B. thekey
andreverse
arguments are now “keyword-only”.- The
cmp()
function should be treated as gone, and the__cmp__()
special method is no longer supported. Use__lt__()
for sorting,__eq__()
with__hash__()
, and other rich comparisons as needed. (If you really need thecmp()
functionality, you could use the expression(a > b) - (a < b)
as the equivalent forcmp(a, b)
.)
In Python3 the six rich comparison operators
__lt__(self, other)
__le__(self, other)
__eq__(self, other)
__ne__(self, other)
__gt__(self, other)
__ge__(self, other)
must be provided individually. This can be abbreviated by using functools.total_ordering
.
This however turns out rather unreadable and unpractical most of the time. Still you have to put similar code pieces in 2 funcs - or use a further helper func.
So mostly I prefer to use the mixin class PY3__cmp__
shown below. This reestablishes the single __cmp__
method framework, which was and is quite clear and practical in most cases. One can still override selected rich comparisons.
Your example would just become:
class point(PY3__cmp__):
...
# unchanged code
PY3 = sys.version_info[0] >= 3
if PY3:
def cmp(a, b):
return (a > b) - (a < b)
# mixin class for Python3 supporting __cmp__
class PY3__cmp__:
def __eq__(self, other):
return self.__cmp__(other) == 0
def __ne__(self, other):
return self.__cmp__(other) != 0
def __gt__(self, other):
return self.__cmp__(other) > 0
def __lt__(self, other):
return self.__cmp__(other) < 0
def __ge__(self, other):
return self.__cmp__(other) >= 0
def __le__(self, other):
return self.__cmp__(other) <= 0
else:
class PY3__cmp__:
pass
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