nonstandard behavior of reflected functions

According to http://docs.python.org/reference/datamodel.html , the reflected operands functions like __radd__ "are only called if the left operand does not support the corresponding operation and the operands are of different types. [3] For instance, to evaluate the expression x - y, where y is an instance of a class that has an __rsub__() method, y.__rsub__(x) is called if x.__sub__(y) returns NotImplemented."
Consider the following simple example:
========================== class Quantity(object):
def __add__(self, other): return '__add__ called'
def __radd__(self, other): return '__radd__ called'
class UnitQuantity(Quantity):
def __add__(self, other): return '__add__ called'
def __radd__(self, other): return '__radd__ called'
print 'Quantity()+Quantity()', Quantity()+Quantity() print 'UnitQuantity()+UnitQuantity()', UnitQuantity()+UnitQuantity() print 'UnitQuantity()+Quantity()', UnitQuantity()+Quantity() print 'Quantity()+UnitQuantity()', Quantity()+UnitQuantity() ==========================
The output should indicate that __add__ was called in all four trials, but the last trial calls __radd__. Interestingly, if I comment out the definition of __radd__ in UnitQuantity, then the fourth trial calls __add__ like it should.
I think this may be an important bug. I'm running Python 2.6.4rc1 (r264rc1:75270, Oct 13 2009, 17:02:06) an ubuntu Karmic. Is it a known issue, or am I misreading the documentation?
Thanks, Darren

On Sun, Oct 18, 2009 at 10:50 AM, Darren Dale dsdale24@gmail.com wrote:
According to http://docs.python.org/reference/datamodel.html , the reflected operands functions like __radd__ "are only called if the left operand does not support the corresponding operation and the operands are of different types. [3] For instance, to evaluate the expression x - y, where y is an instance of a class that has an __rsub__() method, y.__rsub__(x) is called if x.__sub__(y) returns NotImplemented."
Consider the following simple example:
========================== class Quantity(object):
def __add__(self, other): return '__add__ called'
def __radd__(self, other): return '__radd__ called'
class UnitQuantity(Quantity):
def __add__(self, other): return '__add__ called'
def __radd__(self, other): return '__radd__ called'
print 'Quantity()+Quantity()', Quantity()+Quantity() print 'UnitQuantity()+UnitQuantity()', UnitQuantity()+UnitQuantity() print 'UnitQuantity()+Quantity()', UnitQuantity()+Quantity() print 'Quantity()+UnitQuantity()', Quantity()+UnitQuantity() ==========================
The output should indicate that __add__ was called in all four trials, but the last trial calls __radd__. Interestingly, if I comment out the definition of __radd__ in UnitQuantity, then the fourth trial calls __add__ like it should.
I think this may be an important bug. I'm running Python 2.6.4rc1 (r264rc1:75270, Oct 13 2009, 17:02:06) an ubuntu Karmic. Is it a known issue, or am I misreading the documentation?
I'm sorry, I should have read further down the page in the documentation:
"Note: 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."

I see the same behaviour, moreover when I change class Quantity to a classic class (removing '(object)'), it works as expected. (i.e. Quanitity.__add__() is called after the fourth print. I run Python 2.6.2 on Vista.
On Sun, Oct 18, 2009 at 7:50 AM, Darren Dale dsdale24@gmail.com wrote:
According to http://docs.python.org/reference/datamodel.html , the reflected operands functions like __radd__ "are only called if the left operand does not support the corresponding operation and the operands are of different types. [3] For instance, to evaluate the expression x - y, where y is an instance of a class that has an __rsub__() method, y.__rsub__(x) is called if x.__sub__(y) returns NotImplemented."
Consider the following simple example:
========================== class Quantity(object):
def __add__(self, other): return '__add__ called'
def __radd__(self, other): return '__radd__ called'
class UnitQuantity(Quantity):
def __add__(self, other): return '__add__ called'
def __radd__(self, other): return '__radd__ called'
print 'Quantity()+Quantity()', Quantity()+Quantity() print 'UnitQuantity()+UnitQuantity()', UnitQuantity()+UnitQuantity() print 'UnitQuantity()+Quantity()', UnitQuantity()+Quantity() print 'Quantity()+UnitQuantity()', Quantity()+UnitQuantity() ==========================
The output should indicate that __add__ was called in all four trials, but the last trial calls __radd__. Interestingly, if I comment out the definition of __radd__ in UnitQuantity, then the fourth trial calls __add__ like it should.
I think this may be an important bug. I'm running Python 2.6.4rc1 (r264rc1:75270, Oct 13 2009, 17:02:06) an ubuntu Karmic. Is it a known issue, or am I misreading the documentation?
Thanks, Darren _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/ehsanamiri%40gmail.com

Ehsan Amiri wrote:
I see the same behaviour, moreover when I change class Quantity to a classic class (removing '(object)'), it works as expected. (i.e. Quanitity.__add__() is called after the fourth print. I run Python 2.6.2 on Vista.
Darren found the explanation further down the page he was reading - the fact that the right operand is an instance of a subclass of the left operand's class makes a difference.
Regards, Nick.
participants (3)
-
Darren Dale
-
Ehsan Amiri
-
Nick Coghlan