Python:该方法__getattribute__和描述符 [英] Python: the __getattribute__ method and descriptors
问题描述
https://docs.python.org/2/howto/descriptor.html
方法新式类对象,以避免在属性查找特殊的外壳使用它们描述来实现。
method objects in new style classes are implemented using descriptors in order to avoid special casing them in attribute lookup.
我明白这一点的方式是,有实现__get__当与一个实例,当没有一个实例和一个类调用未绑定方法对象调用返回绑定方法对象的方法对象类型。文章还指出,这个逻辑是对象.__ getattribute__方法来实现。像这样:
the way I understand this is that there is a method object type that implements __get__ and returns a bound method object when called with an instance and an unbound method object when called with no instance and only a class. the article also states that this logic is implemented in the object.__getattribute__ method. like so:
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
但反对.__ getattribute__本身就是一种方法!那么它是如何绑定到一个对象(不包括无限递归)?如果是特殊的套管在属性查找这是否不能击败删除旧风格的特殊外壳的目的是什么?
however object.__getattribute__ is itself a method! so how is it bound to an object (without infinite recursion)? if it is special cased in the attribute lookup does that not defeat the purpose of removing the old style special casing?
推荐答案
其实,在CPython的默认 __的getAttribute __
执行不的的Python 的方法,但在C,而不是实现,它可以访问对象插槽(条目在C结构重新presenting Python对象)直接,而没有经历讨厌的属性访问程序。
Actually, in CPython the default __getattribute__
implementation is not Python method, but is instead implemented in C. It can access object slots (entries in the C structure representing Python objects) directly, without bothering to go through the pesky attribute access routine.
仅仅因为你的的Python 的code的做到这一点,并不意味着C code的到。 : - )
Just because your Python code has to do this, doesn't mean the C code has to. :-)
如果你实现一个Python __的getAttribute __
的方法,只需要用对象.__的getAttribute __(自我,attrname)
或更好的是,超(YourClassName,个体经营).__的getAttribute __(attrname)
来访问属性对自
。这样,你就不会打任何递归
If you do implement a Python __getattribute__
method, just use object.__getattribute__(self, attrname)
, or better still, super(YourClassName, self).__getattribute__(attrname)
to access attributes on self
. That way you won't hit recursion either.
在CPython的实施,对属性的访问实际上是由的 tp_getattro
插槽在C类型的对象,以回退到的 tp_getattr
插槽。这样,就可以避免递归。
In the CPython implementation, the attribute access is actually handled by the tp_getattro
slot in the C type object, with a fallback to the tp_getattr
slot. That way you can avoid recursing.
要详尽,充分暴露C $ C $Ç做什么,当你使用属性上的实例的访问,这里是全套的函数调用:
To be exhaustive and to fully expose what the C code does, when you use attribute access on an instance, here is the full set of functions called:
-
Python的转换属性到 <$访问C $ C> PyObject_GetAttr() C函数。该实现该功能中查找
tp_getattro
或tp_getattr
为你的类插槽。
Python translates attribute access to a call to the
PyObject_GetAttr()
C function. The implementation for that function looks up thetp_getattro
ortp_getattr
slot for your class.
的对象
类型具有的 tp_getattr
充满用的 _PyObject_GenericGetAttrWithDict
功能。此功能是你的对象.__的getAttribute __
方法(的特殊的表名称和插槽)之间的映射。
The object
type has tp_getattr
filled with the _PyObject_GenericGetAttrWithDict
function. This function is your object.__getattribute__
method (a special table maps between the name and the slot).
此功能可访问实例 __ __字典
通过的 tp_dict
插槽,但对于的描述符的(含方法)中, _PyType_Lookup
功能被使用。
This function can access the instance __dict__
object through the tp_dict
slot, but for descriptors (including methods), the _PyType_Lookup
function is used.
_PyType_Lookup
查找属性的类(超类)。在code使用直接指向 cl_dict
(定制Python类)和 tp_dict
来引用类和类型的字典。
_PyType_Lookup
looks up attributes on the class (and superclasses). The code uses direct pointers to cl_dict
(custom Python classes) and tp_dict
to reference class and type dictionaries.
如果一个描述符是由 _PyType_Lookup
发现它返回到 _PyObject_GenericGetAttrWithDict
并调用 tp_descr_get
的对象( __ __ GET
挂钩)。
If a descriptor is found by _PyType_Lookup
it is returned to _PyObject_GenericGetAttrWithDict
and it calls the tp_descr_get
function on that object (the __get__
hook).
当你访问类本身的属性,而不是 _PyObject_GenericGetAttrWithDict
的类型 - &GT; tp_getattro
插槽是不是由 type_getattro()服务
功能,这需要元类的考虑了。这个版本要求 __ __ GET
过,但离开实例参数设置为无
。
When you access an attribute on the class itself, instead of _PyObject_GenericGetAttrWithDict
, the type->tp_getattro
slot is instead serviced by the type_getattro()
function, which takes meta classes into account too. This version calls __get__
too, but leaves the instance parameter set to None
.
无处这是否code必须递归调用 __的getAttribute __
访问 __字典__
属性,因为它可以简单地伸入直接在C结构。
Nowhere does this code have to recursively call __getattribute__
to access the __dict__
attribute, as it can simply reach into the C structures directly.
这篇关于Python:该方法__getattribute__和描述符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!