实际上,在CPython中,默认
__getattribute__实现不是 Python
方法,而是在C中实现。它可以直接访问对象插槽(代表Python对象的C结构中的条目),而无需费心通过讨厌的属性访问例程。
仅仅因为您的 Python 代码必须执行此 *** 作,并不意味着C代码必须这样做。:-)
如果您确实实现了Python
__getattribute__方法,则只需使用
object.__getattribute__(self,attrname)或更好
super().__getattribute__(attrname)地访问上的属性即可
self。这样,您也不会遇到递归。
在CPython实现中,属性访问实际上是由C类型对象中的
tp_getattro插槽处理的,而后退到
tp_getattrslot。
为了详尽无遗并充分展示C代码的功能,当您在 实例 上使用属性访问时,这里是称为的完整函数集:
Python将属性访问转换为对
PyObject_GetAttr()
C函数的调用。该函数的实现查找您的类的tp_getattro
或tp_getattr
插槽。该
object
类型已用函数填充tp_getattro
插槽,该PyObject_GenericGetAttr
函数将调用委托给_PyObject_GenericGetAttrWithDict
(将*dict
指针设置为NULL
,将suppress
参数设置为0
)。此功能是您的object.__getattribute__
方法(在名称和插槽之间映射一个特殊的表)。该
_PyObject_GenericGetAttrWithDict
函数可以__dict__
通过tp_dict
slot访问实例对象,但是对于 描述符 (包括方法),则使用该_PyType_Lookup
函数。_PyType_Lookup
处理缓存并委托find_name_in_mro
缓存未命中;后者在类(和超类)上查找属性。该代码使用指向tp_dict
MRO中每个类上的插槽的直接指针来引用类属性。如果找到描述符,
_PyType_Lookup
则将其返回_PyObject_GenericGetAttrWithDict
并调用该tp_descr_get
对象上的函数(__get__
挂钩)。
当您访问 类本身
的属性而不是时
_PyObject_GenericGetAttrWithDict,该
type->tp_getattro插槽将由
type_getattro()函数提供服务,该函数也考虑了元类。此版本
__get__也会调用,但将实例参数设置为
None。
该代码无需递归调用
__getattribute__即可访问该
__dict__属性,因为它可以直接直接进入C结构。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)