关于Python中@属性详情的问题

Questions about details of @property in Python

假设我有一个 class 如下:

class MyClass(object):

    def __init__(self, value=None):
        self.attr = value

    @property
    def attr(self):
        # This acts as a getter?
        # Let's call the function "attr_1" as alias
        return self.__attr

    @attr.setter
    def attr(self, value):
        # This acts as a setter?
        # Let's call the function "attr_2" as alias
        self.__attr = value


inst = MyClass(1)

我阅读了 Documentation on Descriptor 并查看了 property class 的实现。

据我所知,当我输入 inst.attr 时,会发生以下情况:

  1. 找到第一个attr(别名attr_1),attr现在是propertyclass的实例,这是一个数据描述符.
    因此,它将覆盖实例字典,这意味着 type(inst).__dict__['attr'].__get__(inst, type(inst)) 被调用。
  2. attr.__get__(inst, type(inst)) 调用 attr.fget(inst),其中 fget() 实际上是 attr(self)("raw" attr_1 函数)。
  3. 最后,attr.fget(inst) returns inst.__attr.

您的问题实际上与属性及其作为数据描述符的工作方式没有直接关系。这就是 Python 伪造标记为以两个下划线开头的私有属性的方式。

>>> inst.__attr

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    inst.__attr
AttributeError: 'MyClass' object has no attribute '__attr'

考虑到您使用带有单个下划线的内部变量编写了代码(通常是说,您不应该碰这个,但我不会强制执行,风险自负):

>>> class MyClass2(object):

    def __init__(self, value=None):
        self.attr = value

    @property
    def attr(self):
        # This acts as a getter?
        # Let's call the function "attr_1" as alias
        return self._attr

    @attr.setter
    def attr(self, value):
        # This acts as a setter?
        # Let's call the function "attr_2" as alias
        self._attr = value


>>> inst2 = MyClass2(1)
>>> inst2._attr
1

您可以通过查看对象的 __dict__

来了解其中的技巧
>>> inst2.__dict__
{'_attr': 1}
>>> inst.__dict__
{'_MyClass__attr': 1}

只是让您相信这与属性无关:

>>> class OtherClass(object):
    def __init__(self, value):
        self.__attr = value
    def get_attr(self):
        return self.__attr
    def set_attr(self, value):
        self.__attr = value


>>> other_inst = OtherClass(1)
>>> other_inst.get_attr()
1
>>> other_inst.__attr

Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    other_inst.__attr
AttributeError: 'OtherClass' object has no attribute '__attr'
>>> other_inst.__dict__
{'_OtherClass__attr': 1}
>>> other_inst._OtherClass__attr
1
>>> other_inst._OtherClass__attr = 24
>>> other_inst.get_attr()
24
>>> inst._MyClass__attr = 23
>>> inst.attr
23

关于你的最后一个问题,我只是认为 Python 中没有这样的约定 类 必须以大写字母开头。 property 并非孤立案例(datetimeitemgettercsv.reader、...)。