Python新样式类不能使用__dict__来更新property属性

标签 python

>>> class foo():
...     @property
...     def o(self):
...             return 'o'
...
>>> f = foo()
>>> f.o
'o'
>>> f.__dict__['o'] = 'f'
>>> f.o
'f'
>>> class foo(object):
...     @property
...     def o(self):
...             return 'o'
...
>>> f = foo()
>>> f.o
'o'
>>> f.__dict__['o'] = 'f'
>>> f.o
'o'

__dict__ 集合没有出现。有什么想法吗?

我认为也许Python内部对待属性的方式有所不同,但我不确定,如果你自己编写一个属性类,那么该集合就会工作,否则就不行。

最佳答案

@property
def o(self):
    return 'o'

这是一个非数据描述符,即没有定义 setter 的属性。因此实例属性可以覆盖此属性。

来自docs :

If an instance’s dictionary has an entry with the same name as a non-data descriptor, the dictionary entry takes precedence.

因此,要更新属性,还要定义其 setter 方法。

并且不要使用实例的 __dict__ 来访问 setter 或 getter,内部 setter 的 f.o = 'f' 实际上会转换为:

type(f).__dict__['o'].__set__(f, 'f')

演示:

class Foo:

    def __init__(self):
        self._o = 'o'

    @property
    def o(self):
        return self._o

    @o.setter
    def o(self, val):
        self._o = val

>>> f = Foo()
>>> f.o
'o'
>>> type(f).__dict__['o'].__set__(f, 'f')
>>> f.o
'f'
>>> f.o = 'zzzz'  #this is equivalent to the previous call.
>>> f.o
'zzzz'
>>> type(f).__dict__['o'].__set__(f, 'foo')
>>> f.o
'foo'

关于Python新样式类不能使用__dict__来更新property属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21850140/

相关文章:

python - 识别语法正确的无意义句子

python - 如何组合 python 列表并根据第一个元素在列表中创建列表?

python - 如何更新 Celery Task ETA?

python - Pandas |在列中列出到二进制列

python - 删除python中numpy数组中的行

python - 使用 beautifulsoup 中的 findAll 过滤结果

Python检查是否有可能通过左跳或右跳到达数组的最右端

python - Scipy:ellipk 和 ellipkm1 之间的区别

python - PyOTP 生成的代码与 Google Authenticator 生成的代码不匹配

python - 从 Python 脚本运行 vi