【问题标题】:don't understand explanations for Python descriptors cannot be instance variables不懂 Python 描述符的解释不能是实例变量
【发布时间】:2018-07-25 07:12:01
【问题描述】:

我正在寻找关于描述符不能是实例变量的理由,并找到了这个post。在@nneonneo 的回答中,他引用了 Python 邮件列表中的回答。我引用了here

答案列出了我怀疑的两个原因:第一个原因,它说

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

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

第二个原因,ObjectHolder 示例,

而不是将“holder.obj”视为简单数据 属性,它将开始在访问时调用描述符协议 到“holder.obj”并最终将它们重定向到不存在的和 无意义的“holder.foo”属性,这肯定不是什么 预期课程的作者。

最初的问题是关于为什么描述符不能是实例变量,第二个原因只是使用现有机制来解释假设情况。我的意思是,如果描述符作为实例变量是有效的,那么应该有一些检查和转换来使其工作。我不认为你可以使用“描述符作为类变量”的机制来解释“描述符作为实例变量”,特别是后者现在不存在,也许可以开发成将来有效。

谢谢,

【问题讨论】:

    标签: python descriptor


    【解决方案1】:

    我怎么强调都不为过:

    行为是设计使然。 [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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多