具有旧式类的Python描述符

时间:2013-05-23 10:50:22

标签: python class descriptor

我试图谷歌一些关于它的东西。为什么非数据描述符适用于旧式类?

文件说他们不应该:
Note that descriptors are only invoked for new style objects or classes (ones that subclass object() or type()).”。

class Descriptor(object):
    def __init__(self):
        self.x = 1

    def __get__(self, obj, cls=None):
        return self.x


class A:
    x = Descriptor()

a = A()
a.x

>>> 1

感谢。

1 个答案:

答案 0 :(得分:4)

您对文档提出质疑是对的。我试图通过CPython sources查找解释,但要注意:我不是专家。

根据我的理解,属性查找和描述符__get__调用发生在instance_getattr2(选择的摘录)中:

v = class_lookup(inst->in_class, name, &klass);
if (v != NULL) {
    f = TP_DESCR_GET(v->ob_type);
    if (f != NULL) {
        PyObject *w = f(v, (PyObject *)inst, (PyObject *)(inst->in_class));
    }
}

所以要么我缺少某些东西,要么实现中没有任何东西需要新式对象(这与文档相矛盾)。

为了记录,我尝试重新编译Python以将描述符调用限制为新的样式类对象,但它实际上带来了巨大的混乱。我在这个过程中了解到类方法本身是作为描述符实现的:这是用于根据用法返回绑定或未绑定方法对象的机制。例如:

>>> class A:
...     def foo():
...         pass
...
>>> A.foo.__get__(None, A)
<unbound method A.foo>
>>> A.foo.__get__(A(), A)
<bound method A.foo of <__main__.A instance at 0x000000000229CC48>>

因此,似乎阻止对旧式对象或类的属性进行描述符调用也会阻止对它们的方法调用,至少在CPython实现时是这样。

再一次,我不是专家,这是我第一次深入Python实现,所以我很可能错了。我已经提交了an issue来试图澄清这一点。