Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python @属性与公共属性_Python_Python 3.x_Oop_Properties - Fatal编程技术网

Python @属性与公共属性

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:

我正在学习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:
            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