Jak zaimplementować __iadd__ dla właściwości Pythona
Próbuję utworzyć właściwość Pythona, w której dodawanie w miejscu jest obsługiwane inną metodą niż pobieranie wartości, dodawanie innej wartości i ponowne przypisywanie. A więc na własnośćx
na obiekcieo
,
o.x += 5
powinien działać inaczej niż
o.x = o.x + 5
Wartośćo.x
w końcu powinien być taki sam, aby nie mylić oczekiwań ludzi, ale chcę sprawić, by miejsce w miejscu było bardziej wydajne. (W rzeczywistości operacja zajmuje dużo więcej czasu niż proste dodanie).
Moim pierwszym pomysłem było zdefiniowanie w klasie
x = property(etc. etc.)
x.__iadd__ = my_iadd
Ale powoduje to błąd AttributeError, prawdopodobnie dlatego, żeproperty
narzędzia__slots__
?
Moja następna próba używa obiektu deskryptora:
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
Jak widać, wyjątkowy__iadd__
metoda nie jest wywoływana. Mam problem ze zrozumieniem, dlaczego tak jest, chociaż przypuszczam, że obiekt__getattr__
w jakiś sposób go omija.
Jak mogę to zrobić? Czy nie otrzymuję punktu deskryptorów? Czy potrzebuję metaklasy?