如何自动生成Python Vector类的重载运算符以避免重复代码?
解决Vector类运算符重载重复代码的方案
当然有办法搞定这种重复代码的问题!你完全不用一次次复制粘贴那些几乎一样的运算符重载方法,利用Python的动态特性就能自动生成它们,既减少冗余又降低出错概率。
核心思路
你的Vector类里,所有运算符重载方法(比如__add__、__radd__)的逻辑高度一致:都是调用私有类方法_op,只是传入的操作符函数(比如operator.add)和rev参数不同。我们可以把这些映射关系整理成一个字典,然后通过动态添加类方法的方式自动生成这些重载方法。
实现方式1:动态在类外生成方法
这种方式适合在现有类的基础上补充方法,代码如下:
import operator class Vector: def __init__(self, value): self._vals = value.copy() @classmethod def _op(cls, this, that, oper, rev=False): assert isinstance(this, cls) if rev: op = lambda a, b : oper(b, a) else: op = oper if isinstance(that, list): result = [op(x, y) for (x, y) in zip(this._vals, that)] elif isinstance(that, cls): result = [op(x, y) for (x, y) in zip(this._vals, that._vals)] else: # assume other is scalar result = [op(x, that) for x in this._vals] return cls(result) def __str__(self): return str(self._vals) # 定义方法名与操作参数的映射 operator_mappings = { '__add__': (operator.add, False), '__radd__': (operator.add, True), '__sub__': (operator.sub, False), '__rsub__': (operator.sub, True), '__mul__': (operator.mul, False), '__rmul__': (operator.mul, True), '__truediv__': (operator.truediv, False), '__rtruediv__': (operator.truediv, True), } # 动态生成并绑定运算符方法 def generate_operator_method(oper, rev): def method(self, other): return Vector._op(self, other, oper, rev) return method for method_name, (oper, rev) in operator_mappings.items(): setattr(Vector, method_name, generate_operator_method(oper, rev))
实现方式2:使用类装饰器(更整洁)
如果你想让类的定义更干净,可以用类装饰器来封装运算符方法的生成逻辑:
import operator def add_vector_operators(cls): # 定义运算符映射 operator_mappings = { '__add__': (operator.add, False), '__radd__': (operator.add, True), '__sub__': (operator.sub, False), '__rsub__': (operator.sub, True), '__mul__': (operator.mul, False), '__rmul__': (operator.mul, True), '__truediv__': (operator.truediv, False), '__rtruediv__': (operator.truediv, True), } # 动态生成方法并绑定到类 def generate_method(oper, rev): def method(self, other): return cls._op(self, other, oper, rev) return method for method_name, params in operator_mappings.items(): setattr(cls, method_name, generate_method(*params)) return cls @add_vector_operators class Vector: def __init__(self, value): self._vals = value.copy() @classmethod def _op(cls, this, that, oper, rev=False): assert isinstance(this, cls) if rev: op = lambda a, b : oper(b, a) else: op = oper if isinstance(that, list): result = [op(x, y) for (x, y) in zip(this._vals, that)] elif isinstance(that, cls): result = [op(x, y) for (x, y) in zip(this._vals, that._vals)] else: # assume other is scalar result = [op(x, that) for x in this._vals] return cls(result) def __str__(self): return str(self._vals)
验证效果
你可以用以下代码测试生成的方法是否正常工作:
v1 = Vector([1, 2, 3]) v2 = Vector([4, 5, 6]) print(v1 + v2) # 输出 [5, 7, 9] print(v1 * 2) # 输出 [2, 4, 6] print(3 + v1) # 输出 [4, 5, 6] print(v2 - v1) # 输出 [3, 3, 3] print(10 / v1) # 输出 [10.0, 5.0, 3.3333333333333335]
额外优势
- 以后如果需要添加新的运算符(比如地板除法
__floordiv__、取模__mod__),只需要在operator_mappings字典里加一行映射即可,不用重复写方法逻辑。 - 避免了复制粘贴可能带来的拼写错误或者参数不一致问题。
内容的提问来源于stack exchange,提问作者MikeL
相关产品推荐
相关产品推荐

