如何在查找过程中使用`__getattribute__`方法?

时间:2017-07-08 21:07:01

标签: python python-3.x

Nutshell中的Python描述:

上述查找过程中涉及的__getattribute__方法如何?

  • 在查找过程中是否在某处调用了__getattribute__方法?

  • 或者,是否通过调用__getattribute__启动查找过程,然后执行两个链接中的所有工作?

感谢。

1 个答案:

答案 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_getattrotp_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 slotPyObject_GenericGetAttr指向type,则type_getattro

PyObject_GenericGetAttrtype_getattro基本上完成了检查描述符,字典,插槽等(基于类型)的所有工作,并尝试返回一个值。如果他们甚至在所有事情之后都找不到它,那么就会引发AttributeError,如果对象的类型定义为__getattr__,那么它将被调用。