Nutshell中的Python描述:
从类中获取属性时的查找过程,例如cls.name
(请参阅Why are the lookup procedures for getting an attribute from a class and from an instance different?中的第一部分)
the lookup procedure when getting an attribute from an instance, e.g. obj.name
上述查找过程中涉及的__getattribute__
方法如何?
在查找过程中是否在某处调用了__getattribute__
方法?
或者,是否通过调用__getattribute__
启动查找过程,然后执行两个链接中的所有工作?
感谢。
答案 0 :(得分:2)
TLDR:属性查询从调用__getattribute__
开始,它完成了链接中提到的所有工作。根据对象的类型调用object.__getattribute__
或type.__getattribute__
。
任何属性查找都会在内部生成LOAD_ATTR
字节码。
>>> import dis
>>> dis.dis(lambda: foo.x)
1 0 LOAD_GLOBAL 0 (foo)
2 LOAD_ATTR 1 (x)
4 RETURN_VALUE
LOAD_ATTR
然后拨打PyObject_GetAttr
。
PyObject_GetAttr
现在在对象的类型上查找tp_getattro
或tp_getattr
(deprecated)个插槽。
PyObject *
PyObject_GetAttr(PyObject *v, PyObject *name)
{
PyTypeObject *tp = Py_TYPE(v);
...
if (tp->tp_getattro != NULL)
return (*tp->tp_getattro)(v, name);
if (tp->tp_getattr != NULL) {
const char *name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL)
return NULL;
return (*tp->tp_getattr)(v, (char *)name_str);
}
...
}
现在,如果一个对象有自己的__getattribute__
实现,那么使用它会根据类型回退到object.__getattribute__
或type.__getattribute__
。如果object
指向tp_getattro
slot,PyObject_GenericGetAttr
指向type
,则type_getattro
。
PyObject_GenericGetAttr
和type_getattro
基本上完成了检查描述符,字典,插槽等(基于类型)的所有工作,并尝试返回一个值。如果他们甚至在所有事情之后都找不到它,那么就会引发AttributeError
,如果对象的类型定义为__getattr__
,那么它将被调用。