不了解Python描述符的说明不能是实例变量

时间:2018-07-25 07:12:02

标签: python descriptor

我正在搜索有关描述符不能为实例变量的基本原理,并发现了此post。在@nneonneo的答案中,他引用了Python邮件列表中的答案。我加了引号here

答案列出了我有疑问的两个原因:第一个原因是,

  

如果“ M”描述符是由某些实例而不是由类定义的,则知道对象“ reg”是Register的实例并不能告诉我有关“ reg.M”是有效的属性还是任何信息。一个错误。

但是我的问题是,如果在__init__()中定义了“ M”描述符,那么 some 实例怎么定义它?初始化后,每个实例都应具有“ M”描述符属性。然后,“ reg.M”应始终为有效属性。

第二个原因,ObjectHolder示例,

  

不是将“ holder.obj”视为简单数据   属性,它将开始在访问时调用描述符协议   到“ holder.obj”,并最终将它们重定向到不存在的   没有意义的“ holder.foo”属性,当然不是   该类的作者。

最初的问题是为什么描述符不能是实例变量,第二个原因只是使用现有机制来解释一个假设情况。我的意思是,如果描述符将作为实例变量有效,则应该进行一些检查和转换以使其起作用。我不认为您可以使用“将描述符作为类变量”的机制来解释“将描述符作为实例变量”,特别是后者目前不存在,并且可能会在将来发展为有效。

谢谢

1 个答案:

答案 0 :(得分:2)

我对此不够强调:

  

该行为是设计使然。 [1]

就是这样。这是实现语言的方式,并且为什么装饰器在类中的使用效果更好。您提供的资源详细说明了为什么装饰器在类上可以更好地工作,所以我不再重复。


关于您的问题...

  

如果在 init ()中定义了“ M”描述符,那么为什么某些实例会定义它?

不是,您是对的。 Ian提出了一个观点,即通常情况下,基于某些条件的每个实例的初始化可能不会等同于“ reg.M”不会引发AttributeError。类装饰器不是这种情况。如果您总是在__init__中初始化,那么就可以了。 直到,例如,有人覆盖您的__init__或对属性执行del。使用课程,您只需要观看课程即可。


  

与其将“ holder.obj”视为简单的数据属性,它将开始在访问“ holder.obj”时调用描述符协议,并最终将它们重定向到不存在且毫无意义的“ holder.foo”属性,当然,这不是班级作者的意图。

好吧,我们假设有一个对象:

>>> a = property(lambda o: o.eggs)
>>> a
<property object at 0x7f9db318a838>

这是完全合法的,对吗?好吧,如果我想将其存储在某个类的实例上怎么办?我会的:

>>> class Foo: pass
...
>>> foo = Foo()
>>> foo.a = a
>>> foo.a
<property object at 0x7f9db318a838>

好的,这很酷!

此处实例装饰器的问题在于,如果Python将装饰器协议应用于a,则不可能实现。键入foo.a将使其尝试评估eggs产生AttributeError。因此,为了具有两种可能的行为,不会在实例foo上调用装饰器协议。

我希望这可以清除它。 :)



[1] https://mail.python.org/pipermail/python-list/2012-January/618572.html
[2] https://mail.python.org/pipermail/python-list/2012-January/618570.html