关于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
时,会发生以下情况:
- 找到第一个
attr
(别名attr_1
),attr
现在是property
class的实例,这是一个数据描述符.
因此,它将覆盖实例字典,这意味着 type(inst).__dict__['attr'].__get__(inst, type(inst))
被调用。
attr.__get__(inst, type(inst))
调用 attr.fget(inst)
,其中 fget()
实际上是 attr(self)
("raw" attr_1
函数)。
- 最后,
attr.fget(inst)
returns inst.__attr
.
第一个问题来了:classMyClass
没有属性__attr
,那么如何解释第3步中的inst.__attr
?
同样,在模拟的setter中,Python如何找到一个属性inst.__attr
来赋值给value
?
还有一个小问题:既然 property
是 class,为什么不用 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
并非孤立案例(datetime
、itemgetter
、csv.reader
、...)。
假设我有一个 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
时,会发生以下情况:
- 找到第一个
attr
(别名attr_1
),attr
现在是property
class的实例,这是一个数据描述符.
因此,它将覆盖实例字典,这意味着type(inst).__dict__['attr'].__get__(inst, type(inst))
被调用。 attr.__get__(inst, type(inst))
调用attr.fget(inst)
,其中fget()
实际上是attr(self)
("raw"attr_1
函数)。- 最后,
attr.fget(inst)
returnsinst.__attr
.
第一个问题来了:class
MyClass
没有属性__attr
,那么如何解释第3步中的inst.__attr
?同样,在模拟的setter中,Python如何找到一个属性
inst.__attr
来赋值给value
?还有一个小问题:既然
property
是 class,为什么不用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
并非孤立案例(datetime
、itemgetter
、csv.reader
、...)。