在getter方法中给dict赋值

Assign value to dict in getter method

我想在返回 class 的 getter 中更改字典。我可以想象这个问题已经得到回答,但我找不到。有类似的问题讨论 reindexing/remapping of keys in a dict 但他们没有回答我的问题。 因此,我的假设是 getter returns self._d 然后查找键 a 并更新值。令我困惑的是赋值 a.d['a'] = 2 并没有改变字典。

class A:
    def __init__(self):
        self._d = None

    @property
    def d(self):
        self._d['a'] = 4 # this line changes the behavior
        return self._d

    @d.setter
    def d(self, value):
        self._d = value

a = A()
a.d = {'a': 1}
a.d['a'] = 2
print("a.d: ", a.d['a']) # prints 4

实际上你最后的打印将它重置为 4。
我建议你在 http://pythontutor.com 这样的可视化工具中查看执行状态。你会明白是怎么回事

如果您向每个函数添加打印语句,您可以看到这里发生了什么:

class A:
    def __init__(self):
        print("init is called")
        self._d = None

    @property
    def d(self):
        print("property is called")
        self._d['a'] = 4 # this line changes the behavior
        return self._d

    @d.setter
    def d(self, value):
        print("setter is called")
        self._d = value

然后我们遍历您的代码:

In [23]: a = A()                                                                                                                                                                                            
init is called

In [24]: a.d                                                                                                                                                                                                
property is called
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-24-ebaff4a357c2> in <module>
----> 1 a.d

<ipython-input-22-687b3aea38f8> in d(self)
      7     def d(self):
      8         print("property is called")
----> 9         self._d['a'] = 4 # this line changes the behavior
     10         return self._d
     11 

TypeError: 'NoneType' object does not support item assignment

In [26]: a.d = {"a": 1}                                                                                                                                                                                     
setter is called

In [27]: a.d                                                                                                                                                                                                
property is called
Out[27]: {'a': 4}

In [28]: a.d["a"] = 2                                                                                                                                                                                       
property is called

首先要注意的是,在赋值之前调用 a.d 会导致错误,因为我们还没有初始化变量。 (这不是你问的,我只是想指出来。)

其次,请注意当您第一次分配 a.d 时会调用 setter,但是当您更新密钥时 不会 — 属性 方法实际上是在更新密钥时调用的。

如果我们添加更多打印语句来打印出 self._dvalue 的值,我们可以看到 self._d["a"] 在被覆盖之前确实等于 2。首先,我们将属性设置为字典,然后我们将访问该属性。

In [4]: a.d = {"a": 2}                                                                                                                                                                                      
self._d: None
value: {'a': 2}
setter is called

In [5]: a.d                                                                                                                                                                                                 
self._d: {'a': 2}
property is called
Out[5]: {'a': 4}

使用这样的打印语句来了解这些功能的工作原理可以帮助您梳理功能。希望这可以帮助您了解内部工作原理,以便您可以调整代码以获得您想要的结果。