Python:__getattribute__方法和描述符

Python:__getattribute__方法和描述符,第1张

Python:__getattribute__方法和描述符

实际上,在CPython中,默认

__getattribute__
实现不是 Python
方法,而是在C中实现。它可以直接访问对象插槽(代表Python对象的C结构中的条目),而无需费心通过讨厌的属性访问例程。

仅仅因为您的 Python 代码必须执行此 *** 作,并不意味着C代码必须这样做。:-)

如果您确实实现了Python

__getattribute__
方法,则只需使用
object.__getattribute__(self,attrname)
或更好
super().__getattribute__(attrname)
地访问上的属性即可
self
。这样,您也不会遇到递归。

在CPython实现中,属性访问实际上是由C类型对象中的

tp_getattro
插槽处理的,而后退到
tp_getattr
slot。

为了详尽无遗并充分展示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结构。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5647956.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存