关于Python中@property的详细信息的问题



假设我有一个如下所示的类:

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)

我阅读了Descriptor上的文档,并查看了property类的实现。

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

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

  • 第一个问题来了:类MyClass没有属性__attr,那么在步骤3中如何解释inst.__attr

  • 类似地,在模拟的setter中,Python如何找到属性inst.__attr来分配value

  • 还有一个琐碎的问题:既然property是一个类,为什么不Property而不是property呢?

您的问题实际上与属性以及它们作为数据描述符的工作方式没有直接关系。这只是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…(。

相关内容

最新更新