Python in a Nutshell describes:
the lookup procedure when getting an attribute from a class, e.g. cls.name
(see the first part in 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
How is the __getattribute__
method involved in the above lookup procedures?
Is the __getattribute__
method called somewhere in the lookup procedures?
Or, are the lookup procedures started by calling __getattribute__
, which then does all the work in the two links?
Thanks.
TLDR: Attribute lookup starts with calling __getattribute__
and it does all the work mentioned in the links. Based on the type of the object either object.__getattribute__
or type.__getattribute__
is called.
Any attribute lookup results in LOAD_ATTR
bytecode internally.
>>> import dis
>>> dis.dis(lambda: foo.x)
1 0 LOAD_GLOBAL 0 (foo)
2 LOAD_ATTR 1 (x)
4 RETURN_VALUE
LOAD_ATTR
then calls PyObject_GetAttr
.
PyObject_GetAttr
now looks for either tp_getattro
or tp_getattr
(deprecated) slot on the object's type.
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);
}
...
}
Now if an object has its own implementation of __getattribute__
then that is used else it falls back to either object.__getattribute__
or type.__getattribute__
based on the type. tp_getattro
slot in case of object
points to PyObject_GenericGetAttr
and for type
it points to type_getattro
.
PyObject_GenericGetAttr
and type_getattro
basically do all the work of checking for descriptors, dictionary, slots etc(based on the type) and try to return a value. If they fail to find it even after everything then AttributeError
is raised and if the object's type defined __getattr__
then it will be invoked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With