Python @属性与公共属性
我正在学习Python3教程,这里有一个简单的例子,我正在努力学习Python @属性与公共属性,python,python-3.x,oop,properties,Python,Python 3.x,Oop,Properties,我正在学习Python3教程,这里有一个简单的例子,我正在努力学习 class P: def __init__(self,x): self.x = x @property def x(self): return self.__x @x.setter def x(self, x): if x < 0: self.__x = 0 elif x > 1000:
class P:
def __init__(self,x):
self.x = x
@property
def x(self):
return self.__x
@x.setter
def x(self, x):
if x < 0:
self.__x = 0
elif x > 1000:
self.__x = 1000
else:
self.__x = x
P类:
定义初始化(self,x):
self.x=x
@财产
def x(自我):
返回自我
@x、 塞特
def x(self,x):
如果x<0:
自。uux=0
elif x>1000:
自整角x=1000
其他:
自
为什么
\uuuu init\uuuuuuu
中的属性x被定义为公共属性,但在用@property
和@x.setter
装饰的函数中,它像私有属性一样被访问。这并不是那么简单,因为它严重依赖python。但我会尽量简单地解释
您有一个类(除了隐式超类对象继承的属性和一些自动包含的内容)2个属性:
>>> P.__dict__
mappingproxy({'__init__': <function __main__.P.__init__>,
'x': <property at 0x2842664cbd8>})
您还可以为实例添加几乎(几乎是因为描述符协议拦截某些操作-请参见下文)任何属性:
>>> p.y = 100
>>> p.__dict__
{'_P__x': 10, 'z': 100}
这就是描述符协议发挥作用的地方。如果访问实例上的属性,它将首先查看实例是否具有该属性。如果实例没有该属性,它将通过描述符协议查看该类!因此,当您访问self.x
时,这大致相当于:type(self.x.。\uuuuu get\uuuuuuuuu(self)
:
同样地,使用self.x=200设置属性将调用type(self.x.。\uuuu set\uuuu(self,200)
:
@属性将通过描述符协议拦截对self
上的x
的任何访问。因此,您不能使用名称x
来存储实例上的实际值,因为它将始终进入类的@属性和@x.setter
(还有x.deleter
,但您尚未实现该函数)。因此,必须使用另一个名称来存储变量
它通常以相同的名称存储,但有一个前导下划线(也便于维护)。实际上,使用两个前导下划线并不是一个好的做法,因为这样很难对类进行子类划分并修改x
属性,而不让名称自己弄乱变量名。对于p
的实例,x()
方法定义了.x
的作用。如果他们访问了self.x
,他们会给自己打电话。非常感谢你的回答,即使是乞丐也能理解!为了确保我的理解正确:类P的属性对象x
重新定义了语法.x
触发的描述符协议,使用\uuuuu get\uuuuuuu
重定向到x(self)”和
\uuu set\uuuuuuuuu`重定向到x(self,x)
。在\uuu init\uuuu
中调用self.x=x
不是公共属性x
的声明,而是调用x(self,x)
,然后定义存储值的实例的受保护属性\ux
。这就是为什么p.\uu dict\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。然而,它不像@property
那样真正地重新定义了描述符协议。只是它使用@property
修饰的函数成为一个数据描述符,而普通方法是非数据描述符,类似\ux
的东西是一个实例变量(它们在查找过程中具有不同的优先级)。但这太令人毛骨悚然了,你的评论很好地总结了这个过程:)
>>> p = P(10)
>>> p.__dict__
{'_P__x': 10}
>>> p.y = 100
>>> p.__dict__
{'_P__x': 10, 'z': 100}
>>> p.x
10
>>> type(p).x.__get__(p)
10
>>> p.x = 200
>>> p.x
200
>>> type(p).x.__set__(p, 100)
>>> p.x
100