It appears that a subclass is considered to "override" the superclass behavior even if all it does is inherit the superclass behavior. This is difficult to see in the __eq__
case because __eq__
is its own reflection, but you can see it more clearly if you use different operators, such as __lt__
and __gt__
, which are each other's reflections:
class A(object):
def __gt__(self,other):
print "GT", self.__class__, other.__class__
def __lt__(self,other):
print "LT", self.__class__, other.__class__
class B(A):
pass
Then:
>>> A() > B()
LT
Note that A.__gt__
was not called; instead, B.__lt__
was called.
The Python 3 documentation is illustrative, in that it states the rule in different words that are technically more accurate (emphasis added):
If the right operand’s type is a subclass of the left operand’s type and that subclass provides the reflected method for the operation, this method will be called before the left operand’s non-reflected method. This behavior allows subclasses to override their ancestors’ operations.
The subclass does indeed "provide" the reflected method, it just provides it via inheritance. If you actually remove the reflected method behavior in the subclass (by returning NotImplemented), the superclass method is correctly called (after the subclass one):
class A(object):
def __gt__(self,other):
print "GT", self.__class__, other.__class__
def __lt__(self,other):
print "LT", self.__class__, other.__class__
class B(A):
def __lt__(self, other):
print "LT", self.__class__, other.__class__
return NotImplemented
>>> A() > B()
LT
GT
So basically this appears to be a documentation bug. It should say that the subclass reflected method is always tried first (for comparison operators), regardless of whether the subclass explicitly overrides the superclass implementation. (As noted by Mark Dickinson in a comment, though, it only works this way for comparison operators, not for the mathematical operator pairs like __add__
/__radd__
.)
In practice, this is unlikely to matter, since the only time you notice it is when the subclass doesn't override the superclass. But in that case, the subclass behavior is by definition the same as the superclass's anyway, so it doesn't really matter which one is called (unless you're doing something dangerous like mutating the object from within the comparison method, in which case you should have been on your guard anyway).