Como implementar __iadd__ para uma propriedade Python
Estou tentando criar uma propriedade Python em que a adição no local é manipulada por um método diferente da recuperação do valor, adicionando outro valor e reatribuindo. Então, para uma propriedadex
em um objetoo
,
o.x += 5
deve funcionar de forma diferente do que
o.x = o.x + 5
O valor deo.x
deve ser o mesmo no final, para não confundir as expectativas das pessoas, mas eu quero fazer o in-loco adicionar mais eficiente. (Na realidade, a operação leva muito mais tempo do que simples adição.)
Minha primeira ideia foi definir, na aula,
x = property(etc. etc.)
x.__iadd__ = my_iadd
Mas isso gera um AttributeError, presumivelmente porqueproperty
implementa__slots__
?
Minha próxima tentativa usa um objeto de descritor:
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
Como você pode ver, o especial__iadd__
método não é chamado. Estou tendo dificuldade em entender por que isso acontece, embora eu suponha que o objeto__getattr__
está de alguma forma ignorando isso.
Como posso fazer isso? Eu não estou recebendo o ponto de descritores? Eu preciso de uma metaclasse?