_u_init上的Python类属性验证__
我试图在下面的代码中使用setter验证类的一个属性。我要验证的属性名为“\uux”,并设置为在“init”方法上传递的参数。当我将“self_uuuux”更改为“self.x”时,它就如我所期望的那样工作了。我想知道的是它是如何使用“self.x”的,而我在getter和setter方法中的任何地方都不返回“x”属性,以及为什么它不使用“self.”_u_init上的Python类属性验证__,python,oop,getter-setter,Python,Oop,Getter Setter,我试图在下面的代码中使用setter验证类的一个属性。我要验证的属性名为“\uux”,并设置为在“init”方法上传递的参数。当我将“self_uuuux”更改为“self.x”时,它就如我所期望的那样工作了。我想知道的是它是如何使用“self.x”的,而我在getter和setter方法中的任何地方都不返回“x”属性,以及为什么它不使用“self.” class P: def __init__(self, x): self.__x = x # not working
class P:
def __init__(self, x):
self.__x = x # not working
# self.x = x # working
@property
def x(self):
return self.__x
@x.setter
def x(self, x):
if x < 0:
self.__x = 0
else:
self.__x = x
p = P(-5)
print(p.x) # prints -5
P类:
定义初始化(self,x):
self.\uuux=x#不工作
#self.x=x#正在工作
@财产
def x(自我):
返回自我
@x、 塞特
def x(self,x):
如果x<0:
自。uux=0
其他:
自
p=p(-5)
印刷品(p.x)#印刷品-5
是这样的。想象一下有一个校园恶霸,我们叫他丹,他以你为目标。还有贝丝,你很喜欢她。通常情况下,你想避开丹和贝丝见面,但丹不在乎,如果他看到你,他会打你的头
现在你也和乔交朋友了。他是个温和的巨人。非常好的人。他说到他家来,他会确保不让丹进来。一切都很好:当丹来到乔的门口时,他已经转身离开了;当贝丝来时,乔让她进来
关键的一点是:它只在丹开门的时候起作用。如果你听到门铃声自己出去,它就不起作用了
在这里,如果你做了self.x=-5,Joe检查号码,发现是Dan,给他打了个零。但是如果你做了自己,乔就再也见不到丹了。你头上有一个防喷器
self.\uux
只是一个变量,它自己无法进行任何检查self.x是一个函数(其中两个函数是真的,一个用于读,一个用于写),它可以做任何它想做的事情-设置self.\uuux
或拒绝。它是这样的。想象一下有一个校园恶霸,我们叫他丹,他以你为目标。还有贝丝,你很喜欢她。通常情况下,你想避开丹和贝丝见面,但丹不在乎,如果他看到你,他会打你的头
现在你也和乔交朋友了。他是个温和的巨人。非常好的人。他说到他家来,他会确保不让丹进来。一切都很好:当丹来到乔的门口时,他已经转身离开了;当贝丝来时,乔让她进来
关键的一点是:它只在丹开门的时候起作用。如果你听到门铃声自己出去,它就不起作用了
在这里,如果你做了self.x=-5,Joe检查号码,发现是Dan,给他打了个零。但是如果你做了自己,乔就再也见不到丹了。你头上有一个防喷器
self.\uux
只是一个变量,它自己无法进行任何检查self.x
是一个函数(其中两个函数是真的,一个用于读,一个用于写),它可以做任何它想做的事情-设置self.\uuuux
或拒绝。让我们从“@decorator”语法开始。它实际上只是语法上的糖,所以
@decorate
def myfunc():
pass
这只是
def myfunc():
pass
myfunc = decorate(myfunc)
请注意,python函数也是对象(以及类和模块FWIW),因此您可以将函数作为参数传递给其他函数、从函数返回函数、将函数存储为变量或属性等
现在使用属性
类(是的,它是一个类):它只是的一个通用实现,它是支持计算属性的python机制
property
的简单python实现看起来大致类似(我忽略了fdel
和\u del\u
部分):
最后:虽然在初始值设定项中创建对象的所有实例属性(\uuuu init\uuuu
方法)是一种很好的做法,但实际上您可以随时随地设置现有属性或新属性。除了少数类型(主要出于实现原因)使用完全不同的方式存储属性(如果您想了解更多信息,可以查找插槽),普通Python对象主要是伪装的dict,因此myobj.foo='bar'
通常只将'bar'
存储在self.\uu dict\uuuu['foo']
。当然,如果不使用计算属性;)
好的,现在我们有了构建块,让我们分析一下你的课堂上发生了什么:
class P:
# let's ignore the initializer for now
@property
def x(self):
return self.__x
@x.setter
def x(self, x):
if x < 0:
self.__x = 0
else:
self.__x = x
当我们这样做时:
p.x = 5
属性解析规则(在对象中实现.\uuuu setattr\uuuuuuuuuuuuuuu(self,name,value)
)实际上会在“p”上查找“x”,找到我们的“x”属性,因为它是一个绑定描述符(它有一个\uuuuuu set\uuuuuuuuuuuuuuuuuuu方法),所以调用x.\uuu set\uuuuuuuuup(p,5)
,这反过来会调用self.fset(p,5)
(cf属性)__()
definition),它将调用p.\u setx(5)
如果我们得到了初始值设定项:
class P:
def __init__(self, x):
self.x = x
# getter / setter / property definition here
然后非常精确的事情发生了(除了p
实例被命名为self
而不是p
)-它实际上最终调用了p.\u setx(self,x)
与原始实现的唯一区别在于,使用属性时有一个decorator,getter和setter函数不会成为类的方法,它们只作为x
属性对象的fget
和fset
属性存在语法,实际上只是语法上的糖分,所以
@decorate
def myfunc():
pass
这只是
def myfunc():
pass
myfunc = decorate(myfunc)
请注意,python函数也是对象(以及类和模块FWIW),因此您可以将函数作为参数传递给其他函数、从函数返回函数、将函数存储为变量或属性等
现在使用属性
类(是的,它是一个类):它只是的一个通用实现,它是支持计算属性的python机制
p的朴素python实现
class P:
def __init__(self, x):
self.x = x
# getter / setter / property definition here