Usando @property decorator en dicts

Estoy tratando de usar el decorador de @property de Python en un dictado de una clase. La idea es que quiero que un cierto valor (llamémoslo ‘mensaje’) se borre después de acceder a él. Pero también quiero otro valor (llámelo ‘last_message’) para que contenga el último mensaje establecido y manténgalo hasta que se establezca otro mensaje. En mi opinión, este código funcionaría:

 >>> class A(object): ... def __init__(self): ... self._b = {"message": "", ... "last_message": ""} ... @property ... def b(self): ... b = self._b ... self._b["message"] = "" ... return b ... @b.setter ... def b(self, value): ... self._b = value ... self._b["last_message"] = value["message"] ... >>> 

Sin embargo, no parece:

 >>> a = A() >>> ab["message"] = "hello" >>> ab["message"] '' >>> ab["last_message"] '' >>> 

¿No estoy seguro de lo que he hecho mal? Me parece que @property no funciona como lo esperaría en los dictados, pero ¿tal vez estoy haciendo algo más fundamental?

Además, sé que podría usar valores individuales en la clase. Pero esto se implementa como una sesión en una aplicación web y necesito que sea un dict. Podría hacer que esto funcione, o hacer que el objeto de la sesión completa simule que es un dictado, o usar variables individuales y piratearlo para que funcione en el rest de la base del código. Preferiría que esto funcionara.

 class MyDict(dict): def __setitem__(self, key, value): if key == 'message': super().__setitem__('message', '') super().__setitem__('last_message', value) else: super().__setitem__(key, value) class A(object): def __init__(self): self._b = MyDict({"message": "", "last_message": ""}) @property def b(self): return self._b a = A() ab['message'] = 'hello' print(ab['message']) # '' print(ab['last_message']) # hello 

Como creo que has descubierto, la razón por la que tu setter no estaba funcionando es porque

 ab['message']='hello' 

Primero accede a ab , que llama al captador de la propiedad b , no a su configurador. El getter devuelve el self._b . Luego self._b['message']='hello' hace que se llame __setitem__ del dict.

Entonces, para solucionar el problema, necesita un MyDict especial (como MyDict ).

Puede que me esté perdiendo lo que está intentando hacer aquí, pero ¿esto resuelve su problema?

 class A(object): def __init__(self): self._b = {'message':'', 'last_message': ''} @property def b(self): b = self._b.copy() self._b['message'] = '' return b @b.setter def b(self, value): self._b['message'] = value self._b['last_message'] = value if __name__ == "__main__": a = A() ab = "hello" print ab print ab print ab["last_message"] 

 $ python dictPropTest.py {'last_message': 'hello', 'message': 'hello'} {'last_message': 'hello', 'message': ''} hello