(top-posting to shorten the reading time) Note that in 2.5
>>> Eq("b") < Eq("a") True Your Eq class didn't define a __lt__, so in 2.5, it inherits the default method, and ends up (in CPython) looking at the object's address, so the first-created object will be less. In this case, it seemed to do the right thing. In python 3, that fallback is gone, and uncomparable things can't be ordered. More details: Python treats the comparisons as almost[*] arbitrary binary operations. There are even some hacks that take advantage of this to use funky notation. This does mean that it doesn't fall back on logical equivalences. It is entirely possible (though pathological) for two objects to be both equal and unequal, or for one to be both less-than the other but not less-than-or-equal. [*]There are two exceptions to the "arbitrary functions" rule. If an operation is not defined by the left operand, python will try to the reversed operation from the right operand. So when you asked for "a>b" you got forwarded to "b<a". There is also a shortcut so that "a is b" ==> (a ==b and not a != b) So why is python 3 different from python 2? Because in python 2, your custom object inherited default behavior that let anything be ordered (unless it took steps to avoid that). That default ends up looking at object address, which is why the first-created object is less. In python 3, there is no such default. -jJ On 11/16/07, Mark Summerfield <[EMAIL PROTECTED]> wrote: > Hi, > > I'm trying to understand Python 3's comparisons. > > class Eq: > def __init__(self, x=""): > self.x = x > def __str__(self): > return self.x > def __eq__(self, other): > return str(self) == str(other) > > class Lt: > def __init__(self, x=""): > self.x = x > def __str__(self): > return self.x > def __lt__(self, other): > return str(self) < str(other) > > class LtEq: > def __init__(self, x=""): > self.x = x > def __str__(self): > return self.x > def __eq__(self, other): > return str(self) == str(other) > def __lt__(self, other): > return str(self) < str(other) > > pairs = ((Eq("a"), Eq("b")), (Lt("a"), Lt("b")), (LtEq("a"), LtEq("b"))) > for a, b in pairs: > print("comparing", type(a)) > try: > print("a < b", a < b) > except TypeError as err: # TypeError, err in Python 2 > print(err) > # etc, for all the other comparisons > > For Python 2 I get this output: > > comparing <type 'instance'> # Eq > a < b True > a <= b True > a == b False > a != b True > a > b False > a >= b False > > comparing <type 'instance'> # Lt > a < b True > a <= b True > a == b False > a != b True > a > b False > a >= b False > > comparing <type 'instance'> #LtEq > a < b True > a <= b True > a == b False > a != b True > a > b False > a >= b False > > Clearly this is bad since class Eq has no ordering and class Lt has no > notion of equality. > > For Python 3 I get this output: > > comparing <class '__main__.Eq'> > unorderable types: Eq() < Eq() > unorderable types: Eq() <= Eq() > a == b False > a != b True > unorderable types: Eq() > Eq() > unorderable types: Eq() >= Eq() > > comparing <class '__main__.Lt'> > a < b True > unorderable types: Lt() <= Lt() > a == b False > a != b True > a > b False > unorderable types: Lt() >= Lt() > > comparing <class '__main__.LtEq'> > a < b True > unorderable types: LtEq() <= LtEq() > a == b False > a != b True > a > b False > unorderable types: LtEq() >= LtEq() > > This is much better in the case of classes Eq and Lt. But I don't > understand why class LtEq does not handle <= or =>. Bear in mind that > for class Eq I only defined ==, Python 3 created != for me; similarly > for class Lt I defined < and Python created >. Or is my code for LtEq > wrong? > > I know it isn't a problem creating a class decorator or metaclass to > "complete" LtEq; I'm just trying to understand how Python 3 comparisons > work. > > Thanks! _______________________________________________ Python-3000 mailing list Python-3000@python.org http://mail.python.org/mailman/listinfo/python-3000 Unsubscribe: http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com