[Python-Dev] New style classes and operator methods

Greg Ewing greg.ewing at canterbury.ac.nz
Fri Apr 8 07:03:42 CEST 2005


I think I've found a small flaw in the implementation
of binary operator methods for new-style Python classes.

If the left and right operands are of the same class,
and the class implements a right operand method but
not a left operand method, the right operand method
is not called. Instead, two attempts are made to call
the left operand method.

I'm surmising this is because both calls are funnelled
through the same C-level method, which is using the
types of the operands to decide whether to call the
left or right Python methods.

I suppose this isn't really a serious problem, since
it's easily worked around by always defining at least
a left operand method. But I thought I'd point it out
anyway.

The following example illustrates the problem:


class NewStyleSpam(object):

   def __add__(self, other):
     print "NewStyleSpam.__add__", self, other
     return NotImplemented

   def __radd__(self, other):
     print "NewStyleSpam.__radd__", self, other
     return 42

x1 = NewStyleSpam()
x2 = NewStyleSpam()
print x1 + x2


which produces:

NewStyleSpam.__add__ <__main__.NewStyleSpam object at 0x4019062c> 
<__main__.NewStyleSpam object at 0x4019056c>
NewStyleSpam.__add__ <__main__.NewStyleSpam object at 0x4019062c> 
<__main__.NewStyleSpam object at 0x4019056c>
Traceback (most recent call last):
   File "/home/cosc/staff/research/greg/tmp/foo.py", line 27, in ?
     print x1 + x2
TypeError: unsupported operand type(s) for +: 'NewStyleSpam' and 'NewStyleSpam'


Old-style classes, on the other hand, work as expected:


class OldStyleSpam:

   def __add__(self, other):
     print "OldStyleSpam.__add__", self, other
     return NotImplemented

   def __radd__(self, other):
     print "OldStyleSpam.__radd__", self, other
     return 42

y1 = OldStyleSpam()
y2 = OldStyleSpam()
print y1 + y2


produces:

OldStyleSpam.__add__ <__main__.OldStyleSpam instance at 0x4019054c> 
<__main__.OldStyleSpam instance at 0x401901ec>
OldStyleSpam.__radd__ <__main__.OldStyleSpam instance at 0x401901ec> 
<__main__.OldStyleSpam instance at 0x4019054c>
42

-- 
Greg Ewing, Computer Science Dept, +--------------------------------------+
University of Canterbury,	   | A citizen of NewZealandCorp, a	  |
Christchurch, New Zealand	   | wholly-owned subsidiary of USA Inc.  |
greg.ewing at canterbury.ac.nz	   +--------------------------------------+


More information about the Python-Dev mailing list