【问题标题】:Look up an attribute from an instance从实例中查找属性
【发布时间】:2017-12-08 08:54:43
【问题描述】:

简而言之,来自 Python

从实例中获取属性

当您使用语法x.name 来引用 C 类的实例 x ,查找分三步进行:

  1. 当在C(或C 的祖先类之一)中找到name 作为覆盖描述符v 的名称时(即, type(v) 提供方法 __get____set__)

    x.name 的值是type(v).__get__(v, x, C) 的结果

  2. 否则,当namex.__dict__ 中的键时

    x.name 获取并返回x.__dict__['name'] 处的值

  3. 否则,x.name 将查找委托给x 的类(根据与C.name 相同的两步查找,就像刚才 详细)

    当找到描述符v时, 属性查找同样是type(v).__get__(v, x, C)

    • 当找到非描述符值v 时,总 属性查找的结果就是v

当这些查找步骤未找到属性时,Python 会引发 AttributeError 异常。但是,对于 x.name 的查找,当 C 定义或继承特殊的 方法 __getattr__ ,Python 调用 C.__getattr__(x,'name') 而不是提升 例外。然后由__getattr__ 返回合适的值或提高 适当的例外,通常是AttributeError

  1. 步骤 1 和步骤 3 的第一部分是否相同?如果是,为什么同一个步骤会出现两次?

  2. nameC(或C 的祖先类之一中)作为覆盖描述符v 的名称时,它们是否都会发生 em>?


__getattribute__(self, name) 

在每个访问属性x.y 的请求中,Python 调用 x.__getattribute__('y'),必须获取并返回属性 价值或提高AttributeError。的正常语义 属性访问(使用x.__dict__C.__slots__C的类 属性,x.__getattr__) 都归功于object.__getattribute__。 当C 类覆盖__getattribute__ 时,它必须实现所有 它想要提供的属性访问语义。大多数时候,最 实现属性访问语义的便捷方法是 委派(例如,调用 object.__getattribute__(self, ...) 作为一部分 __getattribute__ 的覆盖操作)。

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    步骤 1 和步骤 3 的第一部分是否相同?如果是,为什么同一个步骤会出现两次?

    第 1 步需要 __get____set__(尽管实际上,__set____delete__ 以及 __get__ 都会触发它)。如果通过第 1 步或第 2 步未找到该属性,则第 3 步无条件发生。

    它们是否都发生在“当在 C(或 C 的一个祖先类)中找到名称作为覆盖描述符 v 的名称时”?

    没有。 “覆盖描述符”触发第 1 步;另一种描述符或非描述符将仅在步骤 3 中考虑。(官方 Python 文档不使用术语“覆盖描述符”;他们将带有 __set____delete__ 的描述符称为“数据描述符”,如果数据描述符有__get__,则__get__ 将优先于在实例字典中找到的对象。)

    【讨论】:

    • 谢谢。当它们限定“描述符”时,“覆盖”和“非覆盖”是什么意思?
    • @Tim:他们只是指它是否覆盖了在实例字典中找到的值。
    • 谢谢。 (1) 某些文件中是否提到了“__set____delete__ 以及 __get__ 都会触发它”? (2) 在“如果数据描述符有__get____get__ 将优先于在实例字典中找到的对象”,你的意思是__set__ 而不是__get__
    • @Tim: docs.python.org/3/reference/datamodel.html#invoking-descriptors,不,我的意思是__get__
    • 来自同一个文档链接:“通常,描述符是具有“绑定行为”的对象属性,其属性访问已被描述符协议中的方法覆盖:__get__()、@987654340 @ 和 __delete__()。如果为对象定义了这些方法中的任何,则称其为描述符。”
    猜你喜欢
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 2016-12-01
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-09
    相关资源
    最近更新 更多