"George Sakkis" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] > Steven D'Aprano wrote: > >> I'm writing a class that implements rich comparisons, and I find myself >> writing a lot of very similar code. If the calculation is short and >> simple, I do something like this: >> >> >> class Parrot: >> def __eq__(self, other): >> return self.plumage() == other.plumage() <snip> >> If the comparison requires a lot of work, I'll do something like this: >> >> class Aardvark: >> def __le__(self, other): >> return lots_of_work(self, other) >> def __gt__(self, other): >> return not self <= other <snip> > Once upon a time I had written a metaclass to generate the boilerate, > filling in the gaps. It doesn't impose any constraints on which > comparisons you must implement, e.g you may implement __le__ and > __eq__, or __gt__ and __ne__, etc. Season to taste. > > http://rafb.net/p/mpvsIQ37.nln.html > > George >
Just a side note on writing these comparison operators. I remember when learning Java that this was really the first time I spent so much time reading about testing-for-identity vs. testing-for-equality. The Java conventional practice at the time was to begin each test-for-equality method by testing to see if an object were being compared against itself, and if so, cut to the chase and return True (and the converse for an inequality comparison). The idea behind this was that there were ostensibly many times in code where an object was being compared against itself (not so much in an explicit "if x==x" but in implicit tests such as list searching and filtering), and this upfront test-for-identity, being very fast, could short-circuit an otherwise needless comparison. In Python, this would look like: class Parrot: def __eq__(self, other): return self is other or self.plumage() == other.plumage() def __ne__(self, other): return self is not other and self.plumage() != other.plumage() def __lt__(self, other): return self is not other and self.plumage() < other.plumage() def __gt__(self, other): return self is not other and self.plumage() > other.plumage() def __le__(self, other): return self is not other and self.plumage() <= other.plumage() def __ge__(self, other): return self is not other and self.plumage() >= other.plumage() and George's metaclass would have similar changes. On the other hand, I haven't seen this idiom in any Python code that I've read, and I wonder if this was just a coding fad of the time. Still, in cases such as Steven's Aardark class, it might be worth bypassing something that calls lots_of_work if you tested first to see if self is not other. -- Paul -- http://mail.python.org/mailman/listinfo/python-list