大佬教程收集整理的这篇文章主要介绍了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@H_849_4@mRO中每个类上的插槽的直接指针来引用类属性。
如果找到描述符,_PyType_Lookup
则将其返回_PyObject_GenericGetAttrWithDict
并调用该tp_descr_get
对象上的函数(__get__
挂钩)。
当您访问 类本身
的属性而不是时_PyObject_GenericGetAttrWithDict
,该type->tp_getattro
插槽将由type_getattro()
函数提供服务,该函数也考虑了元类。此版本__get__
也会调用,但将实例参数设置为None
。
该代码无需递归调用__getattribute__
即可访问该__Dict__
属性,因为它可以直接直接进入C结构。
根据关于python描述符的本指南https://docs.python.org/howto/descriptor.html
新样式类中的方法对象是使用描述符实现的,以避免在属性查找中使用特殊的大小写。
我的理解方式是,有一个方法对象类型,该方法对象类型__get__
在使用实例调用时实现并返回一个绑定方法对象,而在没有实例且仅一个类调用时实现一个非绑定方法对象。该文章还指出,该逻辑已在该object.__getattribute__
方法中实现。像这样:
def __getattribute__(self,key):
"Emulate type_getattro() in Objects/typeobject.c"
v = object.__getattribute__(self,key)
if hasattr(v,'__get__'):
return v.__get__(None,self)
return v
但是object.__getattribute__
本身就是一种方法!那么如何将其绑定到对象(无穷递归)?如果在属性查找中有特殊情况,这是否会达到删除旧样式特殊大小写的目的?
以上是大佬教程为你收集整理的Python:__getattribute__方法和描述符全部内容,希望文章能够帮你解决Python:__getattribute__方法和描述符所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。