Python __mul__ 方法
最后修改于 2025 年 4 月 8 日
这份综合指南探讨了 Python 的 __mul__
方法,这是一个用于实现乘法运算符重载的特殊方法。我们将涵盖基本用法、交换律运算、矩阵乘法和实际示例。
基本定义
__mul__
方法被调用以实现乘法运算符 (*
)。当你编写 x * y
时,Python 尝试调用 x.__mul__(y)
。
关键特性:它必须返回乘法的结果,可以在任何类中定义,并且应该处理类型检查。对于交换律运算,还应该实现 __rmul__
。
基本 __mul__ 实现
这是一个简单的实现,展示了如何为自定义类重载乘法运算符。 此示例创建一个 Vector 类。
class Vector: def __init__(self, x, y): self.x = x self.y = y def __mul__(self, scalar): if isinstance(scalar, (int, float)): return Vector(self.x * scalar, self.y * scalar) return NotImplemented def __repr__(self): return f"Vector({self.x}, {self.y})" v = Vector(2, 3) print(v * 3) # Vector(6, 9)
此示例显示了向量与标量的乘法。 __mul__
方法在执行乘法之前检查右操作数是否为数字。
返回 NotImplemented
告诉 Python 尝试其他方法,例如右操作数上的 __rmul__
(如果可用)。
实现交换律乘法
为了处理左操作数不支持乘法但右操作数支持的情况,我们实现了 __rmul__
。
class Vector: def __init__(self, x, y): self.x = x self.y = y def __mul__(self, scalar): if isinstance(scalar, (int, float)): return Vector(self.x * scalar, self.y * scalar) return NotImplemented def __rmul__(self, scalar): return self.__mul__(scalar) def __repr__(self): return f"Vector({self.x}, {self.y})" v = Vector(2, 3) print(v * 3) # Vector(6, 9) print(3 * v) # Vector(6, 9)
通过实现 __rmul__
,v * 3
和 3 * v
都能正确工作。 当左操作数不知道如何与右操作数相乘时,将调用 __rmul__
。
由于标量乘法满足交换律,因此该实现仅委托给 __mul__
。
使用 __matmul__ 进行矩阵乘法
Python 3.5+ 引入了用于矩阵乘法的 @
运算符,通过 __matmul__
实现。
class Matrix: def __init__(self, data): self.data = data def __matmul__(self, other): if len(self.data[0]) != len(other.data): raise ValueError("Incompatible matrix dimensions") result = [[0] * len(other.data[0]) for _ in range(len(self.data))] for i in range(len(self.data)): for j in range(len(other.data[0])): for k in range(len(other.data)): result[i][j] += self.data[i][k] * other.data[k][j] return Matrix(result) def __repr__(self): return '\n'.join([' '.join(map(str, row)) for row in self.data)) A = Matrix([[1, 2], [3, 4]]) B = Matrix([[5, 6], [7, 8]]) print(A @ B)
此示例使用 @
运算符实现正确的矩阵乘法。 __matmul__
方法执行行和列的点积。
该实现检查兼容的维度并创建一个包含结果的新矩阵。 这与使用 __mul__
的元素级乘法不同。
元素级乘法
对于表示集合的类,你可能需要元素级乘法而不是矩阵乘法。
class Vector: def __init__(self, *components): self.components = components def __mul__(self, other): if isinstance(other, Vector): if len(self.components) != len(other.components): raise ValueError("Vectors must be same length") return Vector(*[a * b for a, b in zip(self.components, other.components)]) return NotImplemented def __repr__(self): return f"Vector{self.components}" v1 = Vector(1, 2, 3) v2 = Vector(4, 5, 6) print(v1 * v2) # Vector(4, 10, 18)
当两个操作数都是向量时,此实现执行元素级乘法。 它在相乘之前检查向量是否具有相同的长度。
结果是一个新向量,其中每个分量是输入向量中相应分量的乘积。
组合不同的类型
__mul__
方法可以在适当的时候处理不同类型之间的运算。 这是一个带有单位的例子。
class Meter: def __init__(self, value): self.value = value def __mul__(self, other): if isinstance(other, (int, float)): return Meter(self.value * other) if isinstance(other, Meter): return self.value * other.value # returns area in square meters return NotImplemented def __rmul__(self, other): return self.__mul__(other) def __repr__(self): return f"{self.value}m" distance = Meter(5) print(distance * 2) # 10m print(3 * distance) # 15m area = distance * Meter(4) print(area) # 20
此示例显示了基于右操作数类型的不同行为。 乘以一个数字会缩放距离,而乘以两个 Meter 实例会返回一个面积。
该实现演示了单个运算符如何在保持类型安全的同时,根据上下文具有不同的含义。
最佳实践
- 类型检查: 始终在操作前验证操作数类型
- 返回 NotImplemented: 对于不支持的类型,启用回退
- 实现 __rmul__: 用于交换律运算
- 文档行为: 明确指定支持的操作
- 考虑性能: 针对大型数据结构进行优化
资料来源
作者
列出所有 Python 教程。