从实例中查找属性 [英] Look up an attribute from an instance

查看: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. 处的值
  4. 否则,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. name 出现在 C(或 C 的祖先之一)时,它们是否都发生 "classes) 作为覆盖描述符的名称 v"?

<小时><块引用>

__getattribute__(self, name)

在每次请求访问属性 x.y 时,Python 调用x.__getattribute__('y'),必须获取和返回属性value 否则引发 AttributeError.的正常语义属性访问(使用x.__dict__C.__slots__C的类属性,x.__getattr__) 都是由于 object.__getattribute__.当类 C 覆盖 __getattribute__ 时,它必须实现所有它想要提供的属性访问语义.大多数时候,最实现属性访问语义的便捷方法是委托(例如,调用 object.__getattribute__(self, ...) 作为一部分覆盖 __getattribute__ 的操作).

解决方案

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

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

<块引用>

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

没有.覆盖描述符"触发第 1 步;另一种描述符或非描述符只会在第 3 步中考虑.(官方 Python 文档不使用术语覆盖描述符";它们指的是带有 __set__ 的描述符>__delete__ 作为数据描述符",并且如果数据描述符具有 __get__,则 __get__ 将优先于在实例字典中找到的对象.)

From Python in a Nutshell

Getting an attribute from an instance

When you use the syntax x.name to refer to an attribute of instance x of class C , the lookup proceeds in three steps:

  1. When name is found in C (or in one of C’s ancestor classes) as the name of an overriding descriptor v (i.e., type(v) supplies methods __get__ and __set__ )

    The value of x.name is the result of type(v).__get__(v, x, C)

  2. Otherwise, when name is a key in x.__dict__

    x.name fetches and returns the value at x.__dict__['name']

  3. Otherwise, x.name delegates the lookup to x’s class (according to the same two-step lookup used for C.name, as just detailed)

    When a descriptor v is found, the overall result of the attribute lookup is, again, type(v).__get__(v, x, C)

    • When a nondescriptor value v is found, the overall result of the attribute lookup is just v

When these lookup steps do not find an attribute, Python raises an AttributeError exception. However, for lookups of x.name , when C defines or inherits the special method __getattr__ , Python calls C.__getattr__(x,'name') rather than raising the exception. It’s then up to __getattr__ to either return a suitable value or raise the appropriate exception, normally AttributeError .

  1. Are step 1 and the first part of step 3 the same? If yes, why does the same step appear twice?

  2. Do they both happen "when name is found in C (or in one of C’s ancestor classes) as the name of an overriding descriptor v"?


__getattribute__(self, name) 

At every request to access attribute x.y, Python calls x.__getattribute__('y'), which must get and return the attribute value or else raise AttributeError. The normal semantics of attribute access (using x.__dict__, C.__slots__, C’s class attributes, x.__getattr__) are all due to object.__getattribute__. When class C overrides __getattribute__, it must implement all of the attribute access semantics it wants to offer. Most often, the most convenient way to implement attribute access semantics is by delegating (e.g., calling object.__getattribute__(self, ...) as part of the operation of your override of __getattribute__).

解决方案

Are step 1 and the first part of step 3 the same? If yes, why the same step appear twice?

Step 1 requires both __get__ and __set__ (although actually, either __set__ or __delete__ along with __get__ would trigger it). Step 3 happens unconditionally if the attribute isn't found through steps 1 or 2.

Do they both happen "when name is found in C (or in one of C’s ancestor classes) as the name of an overriding descriptor v"?

No. An "overriding descriptor" triggers step 1; another kind of descriptor or a non-descriptor will only be considered in step 3. (The official Python docs don't use the term "overriding descriptor"; they refer to a descriptor with __set__ or __delete__ as a "data descriptor", and if a data descriptor has __get__, the __get__ will take priority over an object found in an instance dict.)

这篇关于从实例中查找属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆