Hyuga <[EMAIL PROTECTED]> writes: > On Nov 21, 4:09 am, Duncan Booth <[EMAIL PROTECTED]> wrote: >> Johannes Bauer <[EMAIL PROTECTED]> wrote: >> > Seems it was removed on purpose - I'm sure there was a good reason for >> > that, but may I ask why? Instead of the sleek __cmp__ function I had >> > earlier, I now have code like: >> >> > def __lt__(self, other): >> > return self.__cmp__(other) < 0 >> >> > def __le__(self, other): >> > return self.__cmp__(other) < 0 >> >> I hope you actually have <= here. >> >> >> >> > def __gt__(self, other): >> > return self.__cmp__(other) > 0 >> >> > def __ge__(self, other): >> > return self.__cmp__(other) >= 0 >> >> > Does anyone know the reason why __cmp__ was discarded? >> >> I think it was because __cmp__ was the backward compatible fallback for >> the newer rich comparison methods and Python 3 cleans up a lot of stuff >> left in just for backward compatibility. In this case it is a cleanup >> too far as in most cases (i.e. those cases where you don't need the full >> complexity of the rich comparisons) __cmp__ is a much simpler solution. >> >> Seehttp://mail.python.org/pipermail/python-dev/2003-March/034073.html >> for Guido's original thoughts. Also, once upon a time pep-3000 >> referred to the removal of __cmp__ but I can't find it in any of the >> current peps. See >> http://mail.python.org/pipermail/python-checkins/2004-August/042959.html >> and >> http://mail.python.org/pipermail/python-checkins/2004-August/042972.html >> where the reference to removal of __cmp__ became "Comparisons other >> than ``==`` and ``!=`` between disparate types will raise an >> exception unless explicitly supported by the type" and the reference >> to Guido's email about removing __cmp__ was also removed. > > Guido's primary argument for removing it seems to be that the code for > supporting both __cmp__ and the rich comparisons is "hairy" and that > it felt really satisfying to remove. I don't think that's a good > enough argument. It was hairy because there are a lot of cases to > check, but I wouldn't say it was crufty. It made sense, and the way > it worked seemed logical enough. I never ran into any problems with > it. And by and far the most common case is to implement some total > ordering for a class. > > Now, as has been pointed out, all you really need to define total > ordering, at least for sorting, is __eq__ and __lt__, which isn't too > bad. But you still lose the ability to make any other sort of > comparison without implementing all the other comparison operators > too.
As classes can be decorated in Python 3, you can write a decorator to make a class totally ordered. Here is a very simplified proof of concept such decorator: def totally_ordered(cls): if not hasattr(cls, '__gt__'): def gt(self, other): return self != other and not self < other cls.__gt__ = gt # Do the same with __le__, __ge__ return cls @totally_ordered class Fraction: def __init__(self, num, den=1): assert den > 0, "denomintator must be > 0" self.num = num self.den = den def __eq__(self, other): return self.num*other.den == self.den*other.num def __lt__(self, other): return self.num*other.den < self.den*other.num >>> q12=Fraction(1, 2) >>> q23=Fraction(2, 3) >>> q12 < q23 True >>> q12 > q23 False Granted it's not as efficient as a __cmp__ function. -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list