Python 中属性查找的优先级顺序(对于实例属性)
python
class NonDataDescriptor:
def __get__(self, instance, owner):
return "descriptor value"
class MyClass:
data = NonDataDescriptor()
def __init__(self):
self.data = "instance value"
m = MyClass()
在 Python 中,属性查找的优先级顺序(对于实例属性)是:
- 如果属性是一个数据描述符(有 __get__ 和 __set__),则调用描述符的 __get__。
- 否则,如果属性存在于实例的 __dict__ 中,则返回实例字典中的值。
- 否则,如果类有 __getattr__ 方法,则调用它。
- 否则,引发 AttributeError。
在我们的例子中:
- MyClass 的类属性 data 是一个非数据描述符(因为只有 __get__,没有 __set__)。
- 在 __init__ 中,我们执行 self.data = "instance value",这会在实例的 __dict__ 中设置一个键 data,值为 "instance value"。
当通过实例 m 访问 data 时,Python 会查找:
- 检查 data 是否是数据描述符。在 m 的类(MyClass)中,data 是一个描述符,但是是一个非数据描述符(没有 __set__),所以它不被视为数据描述符。因此,跳过数据描述符优先级。
- 然后检查实例的 __dict__。由于 m 有实例属性 data(通过 self.data = ... 设置),所以找到它,并直接返回实例字典中的值。
因此,m.data 将返回 "instance value",而不是描述符的 __get__ 返回的值。
所以,print(m.data) 输出:instance value。
如果描述符是一个数据描述符(即有 __set__ 方法),那么即使实例字典中有 data,数据描述符的优先级更高,会调用描述符的 __get__。但这里没有 __set__,所以是非数据描述符,实例字典优先。
因此,答案应该是 "instance value"。
