我将尝试创建一个Python属性,其中就地添加由不同的方法处理,而检索值、添加另一个值并重新分配则由另一种方法处理。因此,对于对象
o
上的属性x
,o.x += 5
应该与之前的工作方式不同
o.x = o.x + 5
o.x
的值最终应该相同,以免混淆人们的期望,但我想使原地添加更有效率。(实际上,此操作比简单加法需要更多时间。)
我的第一个想法是在类中定义:
x = property(etc. etc.)
x.__iadd__ = my_iadd
但是这会引发AttributeError错误,可能是因为property
实现了__slots__
?
我的下一次尝试使用描述符对象:
class IAddProp(object):
def __init__(self):
self._val = 5
def __get__(self, obj, type=None):
return self._val
def __set__(self, obj, value):
self._val = value
def __iadd__(self, value):
print '__iadd__!'
self._val += value
return self
class TestObj(object):
x = IAddProp()
#x.__iadd__ = IAddProp.__iadd__ # doesn't help
>>> o = TestObj()
>>> print o.x
5
>>> o.x = 10
>>> print o.x
10
>>> o.x += 5 # '__iadd__!' not printed
>>> print o.x
15
从上面的代码可以看出,特殊的__iadd__
方法没有被调用。我不太明白为什么会这样,但我猜测是对象的__getattr__
绕过了它。
我该怎么做呢?我没有理解描述符的要点吗?我需要一个元类吗?