[英]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 instancex
of classC
, the lookup proceeds in three steps:当您使用语法
x.name
来引用类C
的实例x
的属性时,查找将分三个步骤进行:
When
name
is found inC
(or in one ofC
's ancestor classes) as the name of an overriding descriptorv
(ie,type(v)
supplies methods__get__
and__set__
)当
name
中发现C
(或在一个C
的祖先类)作为首要的描述符的名称v
(即,type(v)
供给方法__get__
和__set__
)• The value of
x.name
is the result oftype(v).__get__(v, x, C)
•
x.name
的值是type(v).__get__(v, x, C)
的结果type(v).__get__(v, x, C)
Otherwise, when
name
is a key inx.__dict__
否则,当
name
是x.__dict__
的键时•
x.name
fetches and returns the value atx.__dict__['name']
•
x.name
获取并返回x.__dict__['name']
Otherwise,
x.name
delegates the lookup tox
's class (according to the same two-step lookup used forC.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 justv
•找到非描述符值
v
时,属性查找的总结果为v
When these lookup steps do not find an attribute, Python raises an
AttributeError
exception.当这些查找步骤找不到属性时,Python会引发
AttributeError
异常。 However, for lookups ofx.name
, whenC
defines or inherits the special method__getattr__
, Python callsC.__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, normallyAttributeError
.然后由
__getattr__
决定是否返回合适的值或引发合适的异常,通常是AttributeError
。
Are step 1 and the first part of step 3 the same? 步骤1和步骤3的第一部分是否相同? If yes, why does the same step appear twice?
如果是,为什么同一步骤出现两次?
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 callsx.__getattribute__('y')
, which must get and return the attribute value or else raiseAttributeError
.在每次访问属性
xy
请求时,Python都会调用x.__getattribute__('y')
,后者必须获取并返回属性值,否则会引发AttributeError
。 The normal semantics of attribute access (usingx.__dict__
,C.__slots__
,C
's class attributes,x.__getattr__
) are all due toobject.__getattribute__
.属性访问的常规语义(使用
x.__dict__
C.__slots__
,C.__slots__
,C
的类属性x.__getattr__
)都归因于object.__getattribute__
。 When classC
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, callingobject.__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.