Python:该方法__getattribute__和描述符 [英] Python: the __getattribute__ method and descriptors

查看:340
本文介绍了Python:该方法__getattribute__和描述符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


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的默认 __的ge​​tAttribute __ 执行不的的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 __的ge​​tAttribute __ 的方法,只需要用对象.__的ge​​tAttribute __(自我,attrname)或更好的是,超(YourClassName,个体经营).__的ge​​tAttribute __(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 the tp_getattro or tp_getattr slot for your class.

对象类型具有的 tp_getattr 充满用的 _PyObject_GenericGetAttrWithDict 功能。此功能是你的对象.__的ge​​tAttribute __ 方法(的特殊的表名称和插槽)之间的映射。

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必须递归调用 __的ge​​tAttribute __ 访问 __字典__ 属性,因为它可以简单地伸入直接在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆