我正在创建一个简单的角度对象,它是最简单的形式,是一个整数值,当它超过360(回到0)或低于0(回到360)时会重现。我实现了增强赋值的魔术方法,但出于某种原因,这种方法无效。
class Angle:
def __init__(self, angle):
self.angle = angle
def __add__(self, other):
"""Check for recursion, then return the added value."""
val = self.angle + other
while val > 360:
val -= 360
while val < 0:
val += 360
return val
def __radd__(self, other):
"""Reflected addition."""
return self.__add__(other)
def __iadd__(self, other):
"""Augmented addition assignment."""
val = self.__add__(other)
self.angle = val
它为self.angle,=分配一个非类型值。在我看来它应该工作,因为self.__add__()
返回其他添加到self.angle的值,那么为什么不将val
赋给self.angle?
答案 0 :(得分:1)
完全删除__iadd__
方法。
这将使+=
运算符回退到__add__
,这是对不可变类型进行建模的对象的首选行为。
示例:
class Angle(int):
def __init__(self, val):
self.val = val % 360
def __add__(self, other):
return Angle(self.val + other)
def __sub__(self, other):
return Angle(self.val - other)
def __neg__(self):
return Angle(-self.val)
def __repr__(self):
# just for demonstration purposes ok
return str(self.val)
让我们尝试一下......
>>> a = Angle(35)
>>> a
35
>>> a + 400
75
>>> a
35
>>> a += 400
>>> a
75
>>> a - 75
0
>>> a - 76
359
>>> a
75
>>> a -= 76
>>> a
359
不需要__iadd__
或__radd__
,让python为你处理魔法。
答案 1 :(得分:1)
关于__iadd__
(和其他__iXXX__
方法):
这些方法应该尝试就地进行操作(修改 self)并返回结果(可能是,但不一定是, 自)。
您的__iadd__
方法没有“为self.angle
分配非类型”,它返回None
(函数没有显式返回时的默认值),并重新绑定您当前的名称至None
,即:
class Foo(object):
def __init__(self, angle=120):
self.angle = angle
def __add__(self, other):
"""Check for recursion, then return the added value."""
print "Foo.add"
val = self.angle + other
while val > 360:
val -= 360
while val < 0:
val += 360
return val
def __iadd__(self, other):
"""Augmented addition assignment."""
print "Foo.iadd"
val = self.__add__(other)
self.angle = val
f = Foo()
f += 20
print f is None
简而言之:您希望__iadd__
返回有意义的内容,最有可能self
。
答案 2 :(得分:1)
__add__
和__iadd__
都应return
Angle
个对象:
class Angle(object):
def __init__(self, angle):
self.angle = angle % 360
def __add__(self, other):
return Angle(self.angle + other.angle)
def __iadd__(self, other):
return self.__add__(other)
请注意使用angle % 360
来保留angle in range(0, 360)
。
答案 3 :(得分:0)
您需要return self
实施__iadd__
,因为__iadd__
的返回值已分配到+=
运算符的左侧。这就是Python文档中关于就地运算符实现的内容:
这些方法应该尝试就地进行操作(修改self)并返回结果(可能是,但不一定是自己)。
(source)