从坚果壳中的Python
从实例获取属性
当您使用语法
x.name
来引用属性时 类x
的实例C
,查找分三步进行:
在
name
(或其中一个C
的祖先类)中找到C
作为覆盖描述符的名称v
(即type(v)
提供方法__get__
和__set__
)•
x.name
的值是type(v).__get__(v, x, C)
的结果- 处的值
否则,
中的关键字name
是x.__dict__
•
x.name
获取并返回x.__dict__['name']
- 醇>
否则,
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和步骤3的第一部分是否相同?如果是,为什么同一步骤出现两次?
当name
(或其中一个C
的祖先类)中找到C
作为覆盖描述符的名称时,它们是否都发生 v
“
__getattribute__(self, name)
每次访问属性
x.y
的请求都会调用Pythonx.__getattribute__('y')
,必须获取并返回属性 价值或者提高AttributeError
。正常的语义 属性访问(使用x.__dict__
,C.__slots__
,C
的类 属性x.__getattr__
)全部归于object.__getattribute__
。 当类C
覆盖__getattribute__
时,它必须实现所有 它想要提供的属性访问语义。最常见的是,最多 实现属性访问语义的便捷方法是 委派(例如,将object.__getattribute__(self, ...)
称为部分 覆盖__getattribute__
)的操作。
答案 0 :(得分:2)
步骤1和步骤3的第一部分是否相同?如果是,为什么同一步骤出现两次?
第1步需要__get__
和__set__
(实际上,__set__
或__delete__
以及__get__
都会触发它。如果通过步骤1或2找不到属性,则无条件地执行步骤3.
当它们在C(或C的祖先类之一)中找到名称作为覆盖描述符v的名称时,它们是否都会发生?
没有。 “覆盖描述符”触发第1步;另一种描述符或非描述符将仅在步骤3中考虑。(官方Python文档不使用术语“覆盖描述符”;它们引用具有__set__
或__delete__
的描述符作为“数据描述符”,如果数据描述符具有__get__
,则__get__
将优先于实例dict中找到的对象。)