Python __imul__ 方法
最后修改于 2025 年 4 月 8 日
本综合指南将探讨 Python 的 __imul__
方法,即实现原地乘法的特殊方法。我们将介绍基本用法、运算符重载、可变与不可变类型以及实际示例。
基本定义
调用 __imul__
方法来执行原地乘法运算 (*=
)。在可能的情况下,它应修改并返回 self
,但必要时也可以返回新对象。
关键特性:它在可能的情况下原地修改对象,返回结果(通常是 self),并由 *=
运算调用。如果未实现,Python 会回退到 __mul__
,然后是赋值。
基本 __imul__ 实现
这是一个简单的实现,展示了 __imul__
如何与自定义类一起工作。该方法修改对象的状态并返回自身。
class Number: def __init__(self, value): self.value = value def __imul__(self, other): self.value *= other return self def __repr__(self): return f"Number({self.value})" num = Number(5) num *= 3 print(num) # Output: Number(15)
此示例展示了一个基本的 __imul__
实现,该实现修改了实例的 value 属性。该方法返回 self 以允许链式操作。
*=
运算符调用 __imul__
,后者原地更新对象的状态。这比创建新对象更有效。
带可变序列的 __imul__
对于列表等可变序列,__imul__
执行原地重复。此示例演示了与自定义序列的行为。
class MyList: def __init__(self, items): self.items = list(items) def __imul__(self, factor): self.items *= factor return self def __repr__(self): return f"MyList({self.items})" lst = MyList([1, 2]) lst *= 3 print(lst) # Output: MyList([1, 2, 1, 2, 1, 2])
这个自定义列表类实现了 __imul__
来原地乘法其内容。原始对象被修改而不是创建新对象。
该实现委托给内置列表的 *=
操作,该操作有效地处理了重复。这种模式对于包装器来说很常见。
带不可变类型的 __imul__
不可变类型不能原地修改,因此它们的 __imul__
必须返回新对象。此示例显示了行为差异。
class ImmutableNumber: def __init__(self, value): self.value = value def __imul__(self, other): return ImmutableNumber(self.value * other) def __repr__(self): return f"ImmutableNumber({self.value})" num = ImmutableNumber(5) num *= 3 print(num) # Output: ImmutableNumber(15) print(id(num)) # Shows a new object was created
由于不可变对象无法更改其状态,因此 __imul__
返回一个新实例。原始对象保持不变,并且变量被重新分配。
这与 Python 对元组等不可变类型的内置行为相匹配,在这些类型中,*=
会创建一个新对象而不是原地修改。
使用 __imul__ 进行矩阵乘法
对于矩阵等数学对象,__imul__
可以实现原地矩阵乘法。此示例显示了一个简化版本。
class Matrix: def __init__(self, data): self.data = data def __imul__(self, other): if isinstance(other, (int, float)): # Scalar multiplication self.data = [[x * other for x in row] for row in self.data] return self # Matrix multiplication would go here raise TypeError("Unsupported operand type") def __repr__(self): return f"Matrix({self.data})" m = Matrix([[1, 2], [3, 4]]) m *= 2 print(m) # Output: Matrix([[2, 4], [6, 8]])
这个矩阵类通过 __imul__
实现原地标量乘法。该方法检查操作数类型并执行适当的操作。
对于实际的矩阵乘法,您需要实现完整的算法,但这展示了原地修改模式。
将 __imul__ 与其他操作结合使用
__imul__
可以与其他操作结合使用以实现复杂行为。此示例显示了一个跟踪乘法历史的类。
class TrackingNumber: def __init__(self, value): self.value = value self.history = [] def __imul__(self, other): self.history.append((self.value, other)) self.value *= other return self def get_history(self): return self.history def __repr__(self): return f"TrackingNumber({self.value})" num = TrackingNumber(2) num *= 3 num *= 4 print(num) # Output: TrackingNumber(24) print(num.get_history()) # Output: [(2, 3), (6, 4)]
这个类通过跟踪所有原地乘法来扩展基本的数字行为。历史记录存储在列表中,并在每次操作期间进行更新。
该示例演示了 __imul__
如何维护除执行数学运算之外的附加状态。这对于调试或审计很有用。
最佳实践
- 可能时原地修改:遵循 Python 的可变对象约定
- 返回 self:允许方法链接并匹配内置行为
- 处理不同类型:检查操作数类型并在需要时引发 TypeError
- 考虑不可变性:为不可变类型返回新对象
- 记录行为:清楚地说明操作是否为原地操作
资料来源
作者
列出所有 Python 教程。