In fact, in CPython, the default implementation of __getattribute__ not a Python method, but is instead implemented in C. It can directly access object slots (entries in the C structure representing Python objects), without worrying about going through an annoying procedure access to attributes.
Just because your Python code needs to do this does not mean that C code should. :-)
If you implement the Python __getattribute__ method, just use object.__getattribute__(self, attrname) or better yet, super(YourClassName, self).__getattribute__(attrname) to access the attributes on self . This way you will not remove recursion either.
In the CPython implementation, attribute access is actually handled by the tp_getattro slot in an object of type C with a departure from the tp_getattr slot . This way you can avoid recursion.
To be comprehensive and to fully reveal what C code does when you use attribute access in an instance, here is a complete set of functions:
Python translates access to the call attribute of the PyObject_GetAttr() C function . The implementation for this function looks at the tp_getattro or tp_getattr for your class.
The type object has tp_getattr populated with _PyObject_GenericGetAttrWithDict . This function is your object.__getattribute__ (a special table displays between the name and slot).
This function can access the __dict__ object __dict__ via tp_dict slot , but for descriptors (including methods), the _PyType_Lookup function is used .
_PyType_Lookup looks at class attributes (and superclasses). The code uses direct pointers to cl_dict (custom Python classes) and tp_dict to refer to type and type dictionaries.
If the handle is found using _PyType_Lookup , it returns to _PyObject_GenericGetAttrWithDict and calls the tp_descr_get function on this object ( __get__ hook).
When accessing the attribute of the class itself instead of _PyObject_GenericGetAttrWithDict slot type->tp_getattro served by the type_getattro() function , which also takes meta classes into account. This version also calls __get__ , but the instance parameter is set to None .
Nowhere should this code recursively call __getattribute__ to access the __dict__ attribute, because it can just go directly to C.
source share