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