右侧加法
让我们有一个类名示例,它由一个函数 __add__ 组成,该函数接受一个参数并将该参数与类中可用的数据连接起来。首先,Python 查看 x 和 y 的类型来决定是调用 x.__add__ 还是 y.__radd__。由于它们都是相同类型的 Commuter,它首先尝试 x.__add__。
def __init__(self, val):
self.val = val
def __add__(self, other):
print("add", self.val, other)
return self.val + other
first = Computer(1)
second = Computer(2)
print(first + 1)
print(second + 1)
运行结果:
('add', 1, 1)2
('add', 2, 1)
3
但如果我们这样使用:
class Computer:def __init__(self, val):
self.val = val
def __add__(self, other):
print("add", self.val, other)
return self.val + other
# first = Computer(1)
second = Computer(2)
# print(first + 1)
# print(second + 1)
print(1 + second)
会得到如下的错误。
TypeError: unsupported operand type(s) for +: 'int' and 'instance'
如果我们传入字符串呢?
class sample:def __init__(self, value):
self.data = value
def __add__(self, other):
return self.data + other
Ob1 = sample("test")
Ob2 = sample("Operator")
Ob3 = Ob1 + Ob2
print(Ob3)
我们运行上面的代码会得到这样的错误:TypeError: cannot concatenate 'str' and 'instance' objects。
原因是:
Python 会根据 self.val 和 other 的类型来决定是调用 self.val.__add__ 还是 other.__radd__。由于它们是不相关的类型 int 和 Commuter,它首先尝试 int.__add__。
但是 int.__add__ 为不知道的类型返回 NotImplemented,因此 Python 回退到调用 other.__radd__
所以为了解决这个问题,我们使用 __radd__ 函数,它也会添加 this 并返回 other.a + self.a。只有当 + 右侧是实例对象且左边不是实例对象时,Python 才会调用 __radd__
def __init__(self, val):
self.val = val
def __add__(self, other):
print("add", self.val, other)
return self.val + other
def __radd__(self, other):
print("radd", self.val, other)
return other + self.val
x = Computer("Dell")
y = Computer("Mac")
z = x + y
print("x + y =", z)
注意:__radd__ 中的顺序反转,self 变成在 + 的右侧,而 other 在左侧。
运行结果:
('add', 'Dell', <__main__.Computer instance at 0x10b4fed70>)('radd', 'Mac', 'Dell')
('x + y =', 'DellMac')
以下同理:
class sample:def __init__(self, a):
self.a = a
def __add__(self, other):
return self.a + other.a
def __radd__(self, other):
return other.a + self.a
Ob1 = sample("test")
Ob2 = sample("Operator")
Ob3 = Ob2 + Ob1
print(Ob3)
# testOperator
在 __radd__ 中重用 __add__
为了得到没有使用位置限制的真正可对易运算符,有时候只需要重用 __add__ 来实现 __radd__ :
class Computer2:def __init__(self, val):
self.val = val
def __add__(self, other):
return self.val + other
def __radd__(self, other):
return self.__add__(other)class Computer3:
def __init__(self, val):
self.val = val
def __add__(self, other):
return self.val + other
def __radd__(self, other):
return self + other
class Computer4:
def __init__(self, val):
self.val = val
def __add__(self, other):
return self.val + other
__radd__ = __add__
在这些例子中,位于加号右侧的实例出发单一且共享的 __add__ 方法,并将右侧操作数传递给 self,从而能像左侧时一样被处理。