[Python-Dev] Python docs about comparisons vs. CPython reality (original) (raw)
Jan Kaliszewski zuo at kaliszewski.net
Sat Sep 6 13:34:37 CEST 2014
- Previous message: [Python-Dev] Summary of Python tracker Issues
- Next message: [Python-Dev] Python docs about comparisons vs. CPython reality
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Hello,
Are they bugs in the Python docs or just some CPython implementation details that are purposely not documented? (but then, again, some of the docs seem to be at least not precise...):
In https://docs.python.org/3.4/reference/datamodel.html#object._eq_ there is the statement:
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() so that the operators will behave as expected.
On the other hand, in https://docs.python.org/3.4/library/stdtypes.html#comparisons we read:
(in general, lt() and eq() are sufficient, if you want the conventional meanings of the comparison operators)
And, when I try the eq() stuff in CPython it seems that, indeed, the language provides a proper ne() implementation for me automatically (without need to implement ne() explicitly by myself):
Python 3.4.0 (default, Mar 20 2014, 01:28:00)
[...]
>>> class A:
... def __eq__(self, other):
... if hasattr(self, 'x') and hasattr(other, 'x'):
... return self.x == other.x
... return NotImplemented
...
>>> A() == A()
False
>>> A() != A()
True
>>> a = A()
>>> a.x = 1
>>> a1 = A()
>>> a1.x = 1
>>> a2 = A()
>>> a2.x = 2
>>> a == a1
True
>>> a != a1
False
>>> a1 == a1
True
>>> a1 != a1
False
>>> a1 == a2
False
>>> a1 != a2
True
Is it a language guarantee (then, I believe, it should be documented) or just an implementation accident? (then, I believe, it still could be documented as a CPython implementation detail). See also the Python equivalent of the SimpleNamespace class (without ne() implemented explicitly): https://docs.python.org/3/library/types.html#types.SimpleNamespace
On the other hand, the "lt() and eq() are sufficient" statement seems not to be true:
>>> a < a1
False
>>> a <= a1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: A() <= A()
>>> a > a1
False
>>> a >= a1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: A() >= A()
>>> a1 < a2
True
>>> a1 <= a2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: A() <= A()
>>> a1 > a2
False
>>> a1 >= a2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: A() >= A()
On yet another hand, adding le() to that class seems to be perfectly sufficient (without adding gt() and ge()):
>>> def le(self, other):
... if hasattr(self, 'x') and hasattr(other, 'x'):
... return self.x <= other.x
... return NotImplemented
...
>>> A.__le__ = le
>>> a < a1
False
>>> a <= a1
True
>>> a > a1
False
>>> a >= a1
True
>>> a1 < a2
True
>>> a1 <= a2
True
>>> a1 > a2
False
>>> a1 >= a2
False
What of all this stuff is a language guarantee and what is just an implementation accident?
Shouldn't it be documented more accurately?
Cheers. *j
- Previous message: [Python-Dev] Summary of Python tracker Issues
- Next message: [Python-Dev] Python docs about comparisons vs. CPython reality
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]