6

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

文档说他们不应该:
请注意,描述符仅针对新样式对象或类(子类object()或类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

谢谢。

4

1 回答 1

4

您对文档提出质疑是正确的。我已经尝试通过CPython 资源来寻找解释,但请注意:我不是专家。

据我了解,属性查找和描述符__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 实现,所以我很可能是错的。我已经提出了一个问题,试图澄清这一点。

于 2013-05-23T11:50:14.970 回答