11

@propertyクラスのdictでPythonのデコレータを使用しようとしています。アイデアは、特定の値(「メッセージ」と呼びます)がアクセスされた後にクリアされるようにすることです。ただし、別の値(「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ますが、根本的に間違ったことをしているのではないでしょうか。

また、クラスで個々の値を使用できることも知っています。しかし、これはWebアプリケーションのセッションとして実装されており、私はそれがdictである必要があります。これを機能させるか、セッションオブジェクト全体を作成して、それがdictであるかのように見せかけるか、個々の変数を使用して、残りのコードベース全体で機能するようにハッキングすることができます。私はむしろこれを機能させたいだけです。

4

2 に答える 2

17
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プロパティのセッターではなく、ゲッターを呼び出します。ゲッターはdictを返しますself._b。次にself._b['message']='hello'、dict__setitem__が呼び出される原因になります。

したがって、問題を修正するには、特別なdict(のようなMyDict)が必要です。

于 2010-06-29T04:02:49.317 に答える
3

私はあなたがここでやろうとしていることを見逃しているかもしれませんが、これはあなたの問題を解決しますか?

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
于 2010-06-29T03:53:27.560 に答える