Operator commutativity
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Tue Sep 20 21:07:15 EDT 2011
Ethan Furman wrote:
> Peter Pearson wrote:
>> On Mon, 19 Sep 2011 05:48:07 -0700, Ethan Furman <ethan at stoneleaf.us>
>> wrote:
>> [snip]
>>> Also, if the right-hand operand is a subclass of the left-hand operand
>>> then Python will try right-hand_operand.__radd__ first.
>>
>> I don't think it works that way for me:
>>
>> Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
>>>>> class C1():
>> ... def __add__(self, other):
>> ... print "C1.__add__()"
>> ...
>>>>> class C2(C1):
>> ... def __radd__(self, other):
>> ... print "C2.__radd__()"
>> ...
>>>>> C1() + C2()
>> C1.__add__()
>
> Oh, it has to be a new-style class. Sorry.
Even so, I still don't think it quite works the way you have suggested.
class C1(object):
def __add__(self, other):
return "__add__(%s, %s)" % (self, other)
def __radd__(self, other):
return "__radd__(%s, %s)" % (self, other)
class C2(C1):
pass
>>> C1() + C2()
'__add__(<__main__.C1 object at 0xb7f79b0c>, <__main__.C2 object at
0xb7f79b6c>)'
I've tried that in both Python 2.6 and 3.2 and get the same result.
However, consider this slight variation:
class D1(object):
def __add__(self, other):
return "__add__(%s, %s)" % (self, other)
class D2(D1):
def __radd__(self, other):
return "__radd__(%s, %s)" % (self, other)
>>> D1() + D2()
'__radd__(<__main__.D2 object at 0xb7c2c36c>, <__main__.D1 object at
0xb7c2cb0c>)'
After playing around with various combinations of C1, C2, D1 and D2, it
seems to me that the rule is:
If the right-hand argument is a subclass of the left-hand argument, AND also
defines __radd__ directly rather than inheriting it, then its __radd__
method is called before the left-hand argument's __add__ method.
which strikes me as a strangely specific and not very useful rule. I suspect
it might be an accident of implementation rather than a deliberate feature.
--
Steven
More information about the Python-list
mailing list