我试图在下面的代码中使用setter验证类的一个属性。我要验证的属性名为''uux',并设置为通过'init'方法传递的参数。当我期待自我改变的时候。我想知道的是它如何与“self.x”一起工作,而在getter和setter方法中的任何地方都不返回“x”属性,以及为什么它不能与“self.\ux”一起工作?在
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
是这样的。想象一下有一个学校里的恶霸,我们叫他丹,目标是你。还有贝丝,你很喜欢她。正常情况下,你想避开丹和贝丝见面,但丹不在乎,如果他看到你,他会狠狠揍你一顿。在
现在你也和乔交朋友了。他是个温柔的巨人。非常好的人。他说到他家来,他一定不让丹进来。这一切都很好:当丹来到乔的门口时,他已经转过身去;当贝丝来了,乔让她进来。在
关键的一点是:只要丹开门,它就有效。如果你听到门铃,你自己出去,它就不起作用了。在
所以在这里,如果你要
self.x = -5
,Joe会检查数字,看到是Dan,然后给他发送一个0。但如果你这么做了,乔就再也见不到丹了。你头上挨了一拳。在self.__x
只是一个变量,它不能独立进行任何检查。self.x
是一个函数(实际上有两个,一个用于读,一个用于写),它可以做任何它想做的事情-设置{让我们从“@decorator”语法开始。实际上只是语法上的甜点,所以
只是一个简写
^{pr2}$请注意,python函数也是对象(以及类和模块FWIW),因此您可以将函数作为参数传递给其他函数、从函数返回函数、将函数存储为变量或属性等
现在有了} protocol 的通用实现,这是python支持计算属性的机制。在
property
类(是的,它是一个类):它只是the ^{一个简单的python实现}部分):
property
通常类似于(我忽略了fdel
和{最后:虽然在初始值设定项(方法
__init__
方法)中创建一个对象的所有实例属性是一个很好的做法,但实际上您可以随时随地设置现有的或新的属性。除了一些类型(主要是出于实现原因)使用完全不同的方法存储属性(如果您想了解更多信息,可以查找slots
),普通Python对象主要是伪装的dict,因此myobj.foo = 'bar'
通常只将'bar'
存储在self.__dict__['foo']
中。当然,如果不使用计算属性;)好了,现在我们有了构建块,让我们分析一下你的类发生了什么:
这可以改写为
所以现在
当我们这样做时:
属性解析规则(在
object.__setattr__(self, name, value)
中实现)将实际查找“p”上的“x”,找到我们的“x”属性,并且由于它是一个绑定描述符(它有一个__set__
方法),因此调用x.__set__(p, 5)
(cfself.fset(p, 5)
(cfproperty.__set__()
定义),它将调用p._setx(5)
。在如果我们拿回初始值:
然后,非常精确的事情发生了(除了}),它实际上最终调用了
P
实例被命名为self
而不是{P._setx(self, x)
。在与原始实现的唯一区别是使用}属性存在。在
property
有一个修饰符,getter和setter函数不成为类的方法,它们只作为x
属性对象的fget
和{相关问题 更多 >
编程相关推荐