简体   繁体   English

从实例中查找属性

[英]Look up an attribute from an instance

From Python in a Nutshell 从Python总结

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: 当您使用语法x.name来引用类C的实例x的属性时,查找将分三个步骤进行:

  1. When name is found in C (or in one of C 's ancestor classes) as the name of an overriding descriptor v (ie, type(v) supplies methods __get__ and __set__ ) name中发现C (或在一个C的祖先类)作为首要的描述符的名称v (即, type(v)供给方法__get____set__

    The value of x.name is the result of type(v).__get__(v, x, C) x.name的值是type(v).__get__(v, x, C)的结果type(v).__get__(v, x, C)

  2. Otherwise, when name is a key in x.__dict__ 否则,当namex.__dict__的键时

    x.name fetches and returns the value at x.__dict__['name'] x.name获取并返回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) 否则, x.name将查找委托给x的类(根据刚才用于C.name的相同的两步查找, C.name

    When a descriptor v is found, the overall result of the attribute lookup is, again, type(v).__get__(v, x, C) 找到描述符v ,属性查找的总体结果再次是type(v).__get__(v, x, C)

    • When a nondescriptor value v is found, the overall result of the attribute lookup is just v •找到非描述符值v时,属性查找的总结果为v

When these lookup steps do not find an attribute, Python raises an AttributeError exception. 当这些查找步骤找不到属性时,Python会引发AttributeError异常。 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. 但是,对于x.name查找,当C定义或继承特殊方法__getattr__ ,Python会调用C.__getattr__(x,'name')而不是引发异常。 It's then up to __getattr__ to either return a suitable value or raise the appropriate exception, normally AttributeError . 然后由__getattr__决定是否返回合适的值或引发合适的异常,通常是AttributeError

  1. Are step 1 and the first part of step 3 the same? 步骤1和步骤3的第一部分是否相同? 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 " ? 难道他们都发生“在name中找到C (或者在一个C的祖先类)作为压倒一切的描述符的名字v ”?


 __getattribute__(self, name) 

At every request to access attribute xy , Python calls x.__getattribute__('y') , which must get and return the attribute value or else raise AttributeError . 在每次访问属性xy请求时,Python都会调用x.__getattribute__('y') ,后者必须获取并返回属性值,否则会引发AttributeError The normal semantics of attribute access (using x.__dict__ , C.__slots__ , C 's class attributes, x.__getattr__ ) are all due to object.__getattribute__ . 属性访问的常规语义(使用x.__dict__ C.__slots__C.__slots__C的类属性x.__getattr__ )都归因于object.__getattribute__ When class C overrides __getattribute__ , it must implement all of the attribute access semantics it wants to offer. 当类C覆盖__getattribute__ ,它必须实现它要提供的所有属性访问语义。 Most often, the most convenient way to implement attribute access semantics is by delegating (eg, calling object.__getattribute__(self, ...) as part of the operation of your override of __getattribute__ ). 通常,实现属性访问语义的最方便的方法是通过委派(例如,调用object.__getattribute__(self, ...)作为覆盖__getattribute__的操作的一部分)。

Are step 1 and the first part of step 3 the same? 步骤1和步骤3的第一部分是否相同? 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). 步骤1同时需要__get____set__ (尽管实际上, __set____delete__以及__get__都会触发它)。 Step 3 happens unconditionally if the attribute isn't found through steps 1 or 2. 如果在步骤1或2中找不到属性,则将无条件执行步骤3。

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"? 它们都发生“当在C(或C的祖先类之一)中找到名称作为重载描述符v的名称时”吗?

No. An "overriding descriptor" triggers step 1; 否。“覆盖描述符”触发步骤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.) 在步骤3中将只考虑另一种描述符或非描述符。(官方Python文档不使用术语“覆盖描述符”;它们将带有__set____delete__的描述符称为“数据描述符”,并且如果数据描述符具有__get__ ,则__get__将优先于实例字典中找到的对象。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM