实际上,在CPython中,默认的__getattribute__实现不是Python方法,而是在C中实现.它可以直接访问对象槽(C结构中表示Python对象的条目),而无需经过麻烦的属性访问例程.
仅仅因为你的Python代码必须这样做,并不意味着C代码必须这样做. 🙂
如果你实现了一个Python __getattribute__方法,只需使用object .__ getattribute __(self,attrname),或者更好的是,super(YourClassName,self).__ getattribute __(attrname)来访问self上的属性.这样你就不会遇到递归.
在CPython实现中,属性访问实际上由C类型对象中的tp_getattro slot处理,并回退到tp_getattr slot.这样可以避免递归.
为了详尽无遗并完全暴露C代码的作用,当您在实例上使用属性访问时,这里是完整的函数集:
> Python将属性访问转换为对PyObject_GetAttr() C function的调用.implementation for that function查找您的类的tp_getattro或tp_getattr插槽.
>对象类型具有tp_getattr filled和_PyObject_GenericGetAttrWithDict function.此函数是您的对象.__ getattribute__方法(special table在名称和插槽之间映射).
>此函数可以通过tp_dict slot访问实例__dict__对象,但对于描述符(包括方法),使用_PyType_Lookup function.
> _PyType_Lookup在类(和超类)上查找属性.代码使用直接指向cl_dict(自定义Python类)和tp_dict来引用类和类型字典.
>如果_PyType_Lookup找到描述符,则返回_PyObject_GenericGetAttrWithDict,并调用该对象上的tp_descr_get函数(__get__钩子).
当您访问类本身的属性而不是_PyObject_GenericGetAttrWithDict时,类型> tp_getattro槽将由type_getattro() function提供服务,type_getattro() function也会考虑元类.此版本也调用__get__,但将实例参数设置为None.
这段代码必须以递归方式调用__getattribute__来访问__dict__属性,因为它可以直接进入C结构.