我想知道如果我有这样的课
class Test(object):
def __init__(self):
self.a = 20
self.b = 30
obj = Test()
当我执行 obj.a
时,首先调用哪个?
__getattr__
或 getattr
或查找 __dict__['a']
与 setattr
相同
根据 Python 2.7 文档:
目的。 getattr ( _自我_, _名字_)
当属性查找未在通常位置找到该属性时调用(即它不是实例属性,也未在自身的类树中找到)。名称是属性名称。此方法应返回(计算的)属性值或引发 AttributeError 异常。
它说在通常的地方找不到。那是什么平常的地方。我想知道它什么时候被调用
这还有什么区别 object.__getattribute__(self, name)
任何人都可以给我举个例子吗?
原文由 user196264097 发布,翻译遵循 CC BY-SA 4.0 许可协议
这有点复杂。如果您请求对象的属性,下面是 Python 执行的检查顺序。
首先,Python 将检查对象的类是否有
__getattribute__
方法。如果没有定义,它将继承object.__getattribute__
实现查找属性值的其他方法。下一个检查是在对象的类中
__dict__
。然而,即使在那里找到了一个值,它也可能不是属性查找的结果!如果在此处找到,只有“数据描述符”会优先。最常见的数据描述符是property
对象,它是一个函数的包装器,每次访问属性时都会调用该函数。您可以使用装饰器创建一个属性:在这个类中,
myAttr
是一个数据描述符。这仅仅意味着它通过同时拥有__get__
和__set__
方法来实现描述符协议。 Aproperty
是一个数据描述符。如果该类在其
__dict__
中没有任何具有请求名称的内容,object.__getattribute__
搜索其基类(遵循 MRO)以查看是否继承。继承的数据描述符就像对象类中的描述符一样工作。如果找到数据描述符,则调用其
__get__
方法,返回值成为属性查找的值。如果找到一个不是数据描述符的对象,它会被保留一会儿,但不会立即返回。接下来,检查对象自己的
__dict__
的属性。这是找到大多数普通成员变量的地方。如果对象的
__dict__
什么都没有,但是之前通过类(或基类)的搜索发现了除数据描述符之外的其他内容,则它具有下一个优先级。一个普通的类变量将被简单地返回,但“非数据描述符”将得到更多的处理。非数据描述符是具有
__get__
方法但没有__set__
方法的对象。最常见的非数据描述符类型是函数,当从对象作为非数据描述符访问时,函数成为绑定方法(这就是 Python 可以自动将对象作为第一个参数传递的方式)。描述符的__get__
方法将被调用,它的返回值将是属性查找的结果。最后,如果之前的检查均未成功,则将调用
__getattr__
(如果存在)。以下是一些使用稳步增加优先级属性访问机制来覆盖其父类行为的类:
并且,演示了正在运行的类:
O1(
__getattr__
):O2(类变量和非数据描述符):
O3(实例变量,包括一个本地覆盖的方法):
O4(数据描述符,使用
property
装饰器):O5(
__getattribute__
):