如何调用 __add__

use*_*402 2 python numbers python-2.7

class C(object):
  def __init__(self, value):
    self.value = value

  def __add__(self, other):
    if isinstance(other, C):
      return self.value + other.value
    if isinstance(other, Number):
      return self.value + other
    raise Exception("error")


c = C(123)

print c + c

print c + 2

print 2 + c
Run Code Online (Sandbox Code Playgroud)

显然,前两个打印语句将起作用,而第三个语句失败,因为 int. add () 不能处理一个 C 类实例。

246
125
    print 2 + c
TypeError: unsupported operand type(s) for +: 'int' and 'C'
Run Code Online (Sandbox Code Playgroud)

有没有办法来解决这个问题,所以2 + C会导致C.()被调用?

Mar*_*ers 5

您还需要添加__radd__以处理相反的情况:

def __radd__(self, other):
    if isinstance(other, C):
        return other.value + self.value
    if isinstance(other, Number):
        return other + self.value
    return NotImplemented
Run Code Online (Sandbox Code Playgroud)

并注意你不应该引发异常;NotImplemented而是返回单身人士。这样其他对象仍然可以尝试支持__add____radd__支持您的对象,并且也有机会实现添加。

当您尝试添加两种类型aand 时b,Python 首先尝试调用a.__add__(b); 如果该调用返回NotImplementedb.__radd__(a)则改为尝试。

演示:

>>> from numbers import Number
>>> class C(object):
...     def __init__(self, value):
...         self.value = value
...     def __add__(self, other):
...         print '__add__ called'
...         if isinstance(other, C):
...             return self.value + other.value
...         if isinstance(other, Number):
...             return self.value + other
...         return NotImplemented
...     def __radd__(self, other):
...         print '__radd__ called'
...         if isinstance(other, C):
...             return other.value + self.value
...         if isinstance(other, Number):
...             return other + self.value
...         return NotImplemented
... 
>>> c = C(123)
>>> c + c
__add__ called
246
>>> c + 2
__add__ called
125
>>> 2 .__add__(c)
NotImplemented
>>> 2 + c
__radd__ called
125
Run Code Online (Sandbox Code Playgroud)