Using the @property decorator on dicts

I am trying to use the Python @property decorator on a dict in a class. The idea is that I want a specific value (call it "message") to be cleared after it is accessed. But I also want a different value (name it "last_message") to contain the last message set, and keep it until another message is set. In my opinion, this code will 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, this is not like:

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

I'm not sure what I did wrong? It seems to me that @property does not work, as I would expect it on dicts, but maybe I'm doing something else fundamentally wrong?

In addition, I know that I can simply 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 do this work, or make an entire session object to pretend it's a dict, or use separate variables, and hack it into working the rest of the code base. I would rather just make it work.

+6
python dictionary properties setter getter
source share
2 answers
 class MyDict(dict): def __setitem__(self,key,value): if key=='message': dict.__setitem__(self,'message','') dict.__setitem__(self,'last_message',value) else: dict.__setitem__(self,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 

As I think you found the reason your setter wasn’t working is because

 ab['message']='hello' 

first refers to ab , which calls the attribute of property b , not its setter. Getter returns dict self._b . Then self._b['message']='hello' calls the dict __setitem__ call.

So, to fix the problem, you need a special dict (e.g. MyDict ).

+10
source share

Perhaps I am missing what you are trying to do here, but does your problem solve?

 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 
+1
source share

All Articles