语法
object.__mul__(self, other)
Python__mul__() 方法被调用来实现算术乘法运算* 。例如,为了评估表达式x * y ,Python试图调用x.__mul__(y) 。
我们称这种方法为*"* Dunder Method",即*"Double UnderscoreMethod"(也叫"Magic Method")*。
例子
在下面的例子中,你创建了一个自定义类Data ,并覆盖了__mul__() 方法,从而创建了一个新的Data 对象,其值是两个操作数a 和b 的乘积,类型为Data 。
class Data:
def __init__(self, value):
self.value = value
def __mul__(self, other):
return Data(self.value * other.value)
a = Data(21)
b = Data(2)
c = a * b
print(c.value)
# 42
你已经定义了dunder方法,所以产生的两个Data 对象的乘积本身就是一个Data 对象。
print(type(c))
# <class '__main__.Data'>
如果你没有定义__mul__() 方法,Python 会提出一个TypeError 。
如何解决TypeError:对*不支持的操作数类型
考虑下面的代码片段,你试图在没有定义dunder方法的情况下将两个自定义对象相乘__mul__() 。
class Data:
def __init__(self, value):
self.value = value
a = Data(21)
b = Data(2)
c = a * b
print(c.value)
在我的电脑上运行这个导致了以下错误信息。
Traceback (most recent call last):
File "C:\Users\xcent\Desktop\code.py", line 9, in <module>
c = a * b
TypeError: unsupported operand type(s) for *: 'Data' and 'Data'
这个错误的原因是,__mul__() dunder方法从未被定义过,而且默认情况下没有为自定义对象定义该方法。因此,为了解决TypeError: unsupported operand type(s) for * ,你需要在你的类定义中提供__mul__(self, other) 方法,如前所示。
class Data:
def __init__(self, value):
self.value = value
def __mul__(self, other):
return Data(self.value * other.value)
Python的__mul__与__rmul__对比
假设,你想将两个对象x 和y 相乘。
print(x * y)
Python 首先尝试调用左边对象的__mul__() 方法x.__mul__(y) 。但是这可能因为两个原因而失败。
- 方法
x.__mul__()首先没有实现,或者 - 方法
x.__mul__()已经实现,但是返回一个 NotImplemented 值,表明数据类型不兼容。
如果失败了,Python 试图通过调用y.__rmul__() 来解决这个问题,用于反向乘法的右侧运算符y 。如果这个方法被实现了,Python 知道它没有遇到非交换性操作的潜在问题。如果它只是执行y.__mul__(x) 而不是x.__mul__(y) ,那么如果乘法是非交换性的,就会引起错误。这就是为什么需要y.__rmul__(x) ,它表明乘法毕竟是可能的。
因此,x.__mul__(y) 和x.__rmul__(y) 之间的区别是,前者计算x * y 而后者计算y * x - 两者都调用定义在对象x 上的各自的乘法方法。