Я пытаюсь использовать Python @property
декоратор на dict в классе. Идея состоит в том, что я хочу определенное значение (назовите его 'сообщением') быть очищенным после того, как к нему получают доступ. Но я также хочу другое значение (назовите его 'last_message') чтобы содержать последнее сообщение набора и сохранить его до, другое сообщение установлено. В моем уме работал бы этот код:
>>> 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"]
...
>>>
Однако это не кажется:
>>> a = A()
>>> a.b["message"] = "hello"
>>> a.b["message"]
''
>>> a.b["last_message"]
''
>>>
Я не уверен, что я сделал неправильно? Это кажется мне как @property
разве работе не нравится, я ожидал бы это к на dicts, но возможно я делаю что-то еще существенно неправильно?
Кроме того, я знаю, что мог просто использовать отдельные значения в классе. Но это реализовано как сессия в веб-приложении, и мне нужен он, чтобы быть dict. Я мог или сделать эту работу или сделать целый объект сессии притвориться, что это - dict, или используйте отдельные переменные и взломайте его рабочий всюду по остальной части кодовой базы. Я очень просто заставил бы это работать.
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()
a.b['message'] = 'hello'
print(a.b['message'])
# ''
print(a.b['last_message'])
# hello
Как я думаю, вы обнаружили, причина, по которой ваш сеттер не работает, заключается в том, что
a.b['message']='hello'
сначала происходит обращение к a.b
, которое вызывает геттер свойства b
, а не его сеттер. Геттер возвращает дикту self._b
. Затем self._b['message']='hello'
вызывает __setitem__
дикта.
Поэтому, чтобы решить проблему, вам нужен специальный dict (например, MyDict
).
Возможно, я не понимаю, что вы пытаетесь сделать, но решает ли это вашу проблему?
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()
a.b = "hello"
print a.b
print a.b
print a.b["last_message"]
$ python dictPropTest.py
{'last_message': 'hello', 'message': 'hello'}
{'last_message': 'hello', 'message': ''}
hello