I'm trying to use Python's @property
decorator on a dict in a class. The idea is that I want a certain value (call it 'message') to be cleared after it is accessed. But I also want another value (call it 'last_message') to contain the last set message, and keep it until another message is set. In my mind, this code would work:
>>> 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"]
...
>>>
However, it doesn't seem to:
>>> a = A()
>>> a.b["message"] = "hello"
>>> a.b["message"]
''
>>> a.b["last_message"]
''
>>>
I'm not sure what I have done wrong? It seems to me like @property
doesn't work like I would expect it to on dicts, but maybe I'm doing something else fundamentally wrong?
Also, I know that I could just use individual values in the class. But this is implemented as a session in a web application and I need it to be a dict. I could either make this work, or make the whole session object to pretend it's a dict, or use individual variables and hack it into workingness throughout the rest of the code base. I would much rather just get this to work.
Update
Thanks to ~unutbu's help with subclassing dict
, I came up with the following solution and dropped properties altogether:
>>> class MessageDict(dict):
... def __setitem__(self, key, value):
... if key == "message":
... dict.__setitem__(self, "last_message", value)
... dict.__setitem__(self, key, value)
... def __getitem__(self, key):
... value = dict.__getitem__(self, key)
... if key == "message":
... dict.__setitem__(self, key, "")
... return value
...
>>> a = MessageDict({"message": "", "last_message": ""})
>>> a
{'last_message': '', 'message': ''}
>>> a['message'] = "hello"
>>> a['message']
'hello'
>>> a['message']
''
>>> a['last_message']
'hello'
>>>