Greg wrote: > This is my first post here, so if this is not the correct place to ask > this, please direct me to the best place.
This is a good place to get general advice and to discuss potential bugs when you are unsure whether they actually are bugs. If you are sure that you ran into a bug in python or want to suggest an improvement of the documentation where it is wrong or unclear or hard to understand you can report to http://bugs.python.org . > In looking at the py3k documentation for comparing two classes, two > different view points are expressed (at least it seems so to me). > 1) At http://docs.python.org/py3k/reference/datamodel.html: > "There are no implied relationships among the comparison operators. > The truth of x==y does not imply that x!=y is false. Accordingly, when > defining __eq__(), one should also define __ne__()..." > -- This seems to support the view that if in our code, we would like > to use comparison operators <, >, =, !=, etc. then we should define a > __lt__(), __gt__(), __eq__(), __ne__(), etc. for each comparison > operator we would like. > > This appears to contrast > 2) At http://docs.python.org/py3k/library/stdtypes.html: > "Instances of a class cannot be ordered with respect to other > instances of the same class, or other types of object, unless the > class defines enough of the methods __lt__(), __le__(), __gt__(), and > __ge__() (in general, __lt__() and __eq__() are sufficient, if you > want the conventional meanings of the comparison operators)." > -- This seems to imply that to get all of the operators, only > __lt__() and __eq__() need to be defined (just __lt__() should suffice > though I thought). > > So, which is it supposed to be? Or am I reading the documentation > wrong? I agree with you that the documentation is at least unclear. The following experiment suggests that list.sort() works correctly if only __lt__() and __eq__() are implemented which in my reading is what your second quote intends to convey. But "enough of the methods..." is a fuzzy statement. The other finding: (1) a != b is emulated with not (a == b) (2) a > b is emulated with b < a is not something I'd expect after reading your first quote, but technically (2) is covered by """... __lt__() and __gt__() are each other’s reflection ...""" $ cat py3compare.py report = True class A: def __init__(self, key, side="A"): self.key = key self.side = side def __eq__(self, other): result = self.key == other.key if report: print(self, "__eq__", other, "-->", result) return result def __lt__(self, other): result = self.key < other.key if report: print(self, "__lt__", other, "-->", result) return result def __str__(self): return "{}({})".format(self.side, self.key) def __repr__(self): return str(self.key) a = A(1, "L") for k in range(3): b = A(k, "R") print("{} != {}: {}\n".format(a, b, a != b)) print("{} > {}: {}\n".format(a, b, a > b)) print() import random items = [] for n in 10, 20: items.extend(map(A, range(n))) random.shuffle(items) report = False items.sort() print(items) print(a <= b) $ python3 py3compare.py L(1) __eq__ R(0) --> False L(1) != R(0): True R(0) __lt__ L(1) --> True L(1) > R(0): True L(1) __eq__ R(1) --> True L(1) != R(1): False R(1) __lt__ L(1) --> False L(1) > R(1): False L(1) __eq__ R(2) --> False L(1) != R(2): True R(2) __lt__ L(1) --> False L(1) > R(2): False [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] Traceback (most recent call last): File "py3compare.py", line 39, in <module> print(a <= b) TypeError: unorderable types: A() <= A() $ Conclusion: If you can come up with a text that is both correct and clear, don't hesitate to tell us, here or on the bug tracker. Peter PS: The painless way out: always use @functools.total_ordering or the equivalent cookbok recipe. -- http://mail.python.org/mailman/listinfo/python-list