在字典上使用@property 装饰器 [英] Using @property decorator on dicts

查看:36
本文介绍了在字典上使用@property 装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在类中的字典上使用 Python 的 @property 装饰器.这个想法是我希望在访问后清除某个值(称为消息").但我还希望另一个值(称为last_message")包含最后设置的消息,并保留它直到设置另一条消息.在我看来,这段代码会起作用:

<预><代码>>>>A类(对象):... def __init__(self):... self._b = {"message": "",... "last_message": ""}... @财产... def b(self):... b = self._b... self._b["message"] = ""...返回 b... @b.setter... def b(self, value):... self._b = 值... self._b["last_message"] = value["message"]...>>>

然而,它似乎没有:

<预><代码>>>>a = A()>>>a.b["message"] = "你好">>>a.b["消息"]''>>>a.b["last_message"]''>>>

我不确定我做错了什么?在我看来 @property 不像我期望的那样在 dicts 上工作,但也许我在做其他根本错误的事情?

此外,我知道我可以只在类中使用单个值.但是这是作为 Web 应用程序中的会话实现的,我需要它是一个 dict.我可以让这个工作,或者让整个会话对象假装它是一个 dict,或者使用单个变量并将其破解到整个代码库的其余部分.我宁愿让它发挥作用.

解决方案

class MyDict(dict):def __setitem__(self, key, value):如果键 == '消息':super().__setitem__('message', '')super().__setitem__('last_message', value)别的:super().__setitem__(key, value)A类(对象):def __init__(self):self._b = MyDict({"message": "","last_message": ""})@财产定义 b(自我):返回 self._ba = A()a.b['message'] = '你好'打印(a.b['消息'])#''打印(a.b['last_message'])# 你好

我想你已经发现,你的二传手不工作的原因是因为

a.b['message']='hello'

首先访问a.b,它调用b 属性的getter,而不是它的setter.getter 返回字典 self._b.然后 self._b['message']='hello' 导致 dict 的 __setitem__ 被调用.

所以要解决这个问题,你需要一个特殊的字典(比如MyDict).

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.

解决方案

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

As I think you've discovered, the reason why your setter wasn't working is because

a.b['message']='hello'

first accesses a.b, which calls the b property's getter, not its setter. The getter returns the dict self._b. Then self._b['message']='hello' causes the dict's __setitem__ is called .

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

这篇关于在字典上使用@property 装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆