我有一个矢量类:
class Vector:
def __init__(self, x, y):
self.x, self.y = x, y
def __str__(self):
return '(%s,%s)' % (self.x, self.y)
def __add__(self, n):
if isinstance(n, (int, long, float)):
return Vector(self.x+n, self.y+n)
elif isinstance(n, Vector):
return Vector(self.x+n.x, self.y+n.y)
工作正常,即我可以写:
a = Vector(1,2)
print(a + 1) # prints (2,3)
但是,如果操作顺序颠倒,则失败:
a = Vector(1,2)
print(1 + a) # raises TypeError: unsupported operand type(s)
# for +: 'int' and 'instance'
我理解错误:int
对象添加到Vector
对象是未定义的,因为我没有在int
类中定义它。有没有办法解决这个问题而不在int
(或int
的父级)中定义它?
答案 0 :(得分:7)
您还需要定义__radd__
某些操作不一定像这样评估a + b == b + a,这就是Python定义添加和 radd 方法的原因。
更好地解释自己:它支持这样一个事实:“int”没有定义+
操作,class Vector
实例作为操作的一部分。因此,向量+ 1与1 +向量不同。
当Python试图查看1.__add__
方法可以做什么时,会引发异常。 Python继续寻找Vector.__radd__
操作来尝试完成它。
在OP的情况下,评估为 true ,并且足以__radd__ = __add__
class Vector(object):
def __init__(self, x, y):
self.x, self.y = x, y
def __str__(self):
return '(%s,%s)' % (self.x, self.y)
def __add__(self, n):
if isinstance(n, (int, long, float)):
return Vector(self.x+n, self.y+n)
elif isinstance(n, Vector):
return Vector(self.x+n.x, self.y+n.y)
__radd__ = __add__
a = Vector(1, 2)
print(1 + a)
哪个输出:
(2,3)
这同样适用于所有类似数字的操作。
答案 1 :(得分:4)
当您说x + y
时,Python会调用x.__add__(y)
。如果x未实现__add__
(或该方法返回NotImplemented
),则Python会尝试将y.__radd__(x)
作为后备调用。
因此,您所要做的就是在Vector类中定义__radd__()
方法,1 + y
将按预期工作。
注意:您也必须对其他操作执行类似操作,例如:实施__mul__()
和__rmul__()
对等
您可能还想查看this question,它会更详细地解释相同的原则。
<强>更新强>
根据您的使用情况,您可能还希望实施__iadd__()
方法(及其表兄弟)来覆盖+=
运算符。
例如,如果您在此处说y += 1
(y
是Vector
的实例),您可能希望修改y
实例本身,而不是返回结果是新的Vector
实例,这是您__add__()
方法当前所做的事情。