Python 自动生成重载运算符?
考虑以下在Python中使用所有向量操作实现向量对象:Python 自动生成重载运算符?,python,operator-overloading,Python,Operator Overloading,考虑以下在Python中使用所有向量操作实现向量对象: 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:
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 __add__(self, other):
return Vector._op(self, other, operator.add, False)
def __radd__(self, other):
return Vector._op(self, other, operator.add, True)
def __sub__(self, other):
return Vector._op(self, other, operator.sub, False)
def __rsub__(self, other):
return Vector._op(self, other, operator.sub, True)
def __mul__(self, other):
return Vector._op(self, other, operator.mul, False)
def __rmul__(self, other):
return Vector._op(self, other, operator.mul, True)
def __truediv__(self, other):
return Vector._op(self, other, operator.truediv, False)
def __rtruediv__(self, other):
return Vector._op(self, other, operator.truediv, True)
def __str__(self):
return str(self._vals)
很明显,所有重载运算符(\uuuu add\uuuu
,\uu radd\uuuu
,…)都具有完全相同的代码,除了传递给私有类方法\uop
的操作符和rev
参数之外
有没有办法避免所有的复制粘贴和自动(或半自动)这些操作 第一件事:类方法在实例上也可用,所以您应该将方法编写为
def __someop__(self, other):
return self._op(self, other, ...)
或者,很容易获得对象的类型(cls=type(obj)
),因此,除非您有其他理由将\u op
作为类方法,否则您可以将其作为实例方法
现在回答您的问题:从技术上讲,您可以使用自定义元类或类装饰器来创建方法,即:
class VectorType(type):
def __new__(meta, name, bases, attrs):
todo = [
# name, operator, reverse
("__add__", operator.add, False),
("__sub__", operator.sub, False),
# etc
]
for name, oper, rev in todo:
# avoids overriding already defined methods
if name not in attrs:
def f(self, other):
return cls._op(self, other, oper=oper, rev=rev)
attrs[name] = f
return type.__new__(meta, name, bases, attr)
class Vector(metaclass=VectorType):
# etc
但这实际上不会改进您现有的代码,除非您有很多(不相关的)类使用此方案,而且即使是普通的mixin类也可以工作
如果您只有这个类的问题,那么您当前的代码是清晰的、简单的、可读的和显式的,非常符合pythonic。R-version仅在没有正常版本可用时使用。请参阅中的答案。是否总是使用对象的类查找特殊方法?这意味着它们不能像你所说的那样仅仅成为实例方法。@martineau我恐怕听不到你的评论。。。。特殊方法只能在类上查找是的,但这并不意味着它们必须是类方法(实际上也不应该是),而且我建议将其转换为实例方法的唯一方法也不是神奇的方法。@martineau而且看起来你混淆了“实例方法”(iow普通方法,在类上定义,并将实例作为第一个参数),其中“每个实例方法”iow方法添加为实例属性(这显然不是我答案的一部分)