当前位置 : 主页 > 编程语言 > python >

Python 运算法重载之右侧加法

来源:互联网 收集:自由互联 发布时间:2022-06-15
右侧加法 让我们有一个类名示例,它由一个函数 ​​__add__​​ 组成,该函数接受一个参数并将该参数与类中可用的数据连接起来。首先,Python 查看 x 和 y 的类型来决定是调用 ​​

右侧加法

让我们有一个类名示例,它由一个函数 ​​__add__​​ 组成,该函数接受一个参数并将该参数与类中可用的数据连接起来。首先,Python 查看 x 和 y 的类型来决定是调用 ​​x.__add__​​ 还是 ​​y.__radd__​​。由于它们都是相同类型的 Commuter,它首先尝试 ​​x.__add__​​。


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)

运行结果:

('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__​​


class Computer:
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,从而能像左侧时一样被处理。

网友评论