Python如何绕过普通属性查找以找到__dict__? [英] How does Python bypass normal attribute lookup to find `__dict__`?

查看:148
本文介绍了Python如何绕过普通属性查找以找到__dict__?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道obj.__dict__中的__dict__type(obj)的描述符属性,因此对obj.__dict__的查找是type(obj).__dict__['__dict__'].__get__(obj).

I understand that __dict__ in obj.__dict__ is a descriptor attribute of type(obj), so the lookup for obj.__dict__ is type(obj).__dict__['__dict__'].__get__(obj).

来自 https://stackoverflow.com/a/46576009

很容易说__dict__必须是一个描述符,因为 将其实现为__dict__条目将需要您找到 __dict__,然后才能找到__dict__,但是 Python已经存在 查找时绕过普通属性查找以找到__dict__ 其他属性,因此不像最初那样引人注目 声音.如果描述符用'__dict__'键替换 每个__dict____dict__仍然可以找到.

It's tempting to say that __dict__ has to be a descriptor because implementing it as a __dict__ entry would require you to find the __dict__ before you can find the __dict__, but Python already bypasses normal attribute lookup to find __dict__ when looking up other attributes, so that's not quite as compelling as it initially sounds. If the descriptors were replaced with a '__dict__' key in every __dict__, __dict__ would still be findable.

"Python已经如何绕过常规属性查找以找到__dict__"? 常规属性查找"是什么意思?

How does "Python already bypasses normal attribute lookup to find __dict__"? What does "normal attribute lookup" mean?

根据链接中引号的上下文,我认为作者写这篇文章时并没有提到obj.__dict__的查找是type(obj).__dict__['__dict__'].__get__(obj).

According to the context of the quote in the link, I don't think when the author wrote that, he referred to that the lookup for obj.__dict__ is type(obj).__dict__['__dict__'].__get__(obj).

推荐答案

常规属性查找是通过调用 C-API tp_getattro插槽.默认实现是在 PyObject_GenericGetAttr C-API中功能.

Normal attribute lookup is done by calling the __getattribute__ hook, or more precisely, the C-API tp_getattro slot. The default implementation for this is in the PyObject_GenericGetAttr C-API function.

PyObject_GenericGetAttr的工作是调用描述符(如果存在)并查看实例__dict__.确实存在 一个__dict__描述符,但是__getattribute__直接访问实例内存结构中的__dict__插槽更快,这就是

It is the job of PyObject_GenericGetAttr to invoke descriptors if they exist, and to look at the instance __dict__. And indeed, there is a __dict__ descriptor, but it is faster for __getattribute__ to just access the __dict__ slot in the instance memory structure directly, and that is what the actual implementation does:

if (dict == NULL) {
    /* Inline _PyObject_GetDictPtr */
    dictoffset = tp->tp_dictoffset;
    if (dictoffset != 0) {
        if (dictoffset < 0) {
            Py_ssize_t tsize;
            size_t size;

            tsize = ((PyVarObject *)obj)->ob_size;
            if (tsize < 0)
                tsize = -tsize;
            size = _PyObject_VAR_SIZE(tp, tsize);
            assert(size <= PY_SSIZE_T_MAX);

            dictoffset += (Py_ssize_t)size;
            assert(dictoffset > 0);
            assert(dictoffset % SIZEOF_VOID_P == 0);
        }
        dictptr = (PyObject **) ((char *)obj + dictoffset);
        dict = *dictptr;
    }
}

请注意 Inline _PyObject_GetDictPtr 注释;这是一种性能优化,因为实例属性查找非常频繁.

Note the Inline _PyObject_GetDictPtr comment; this is a performance optimisation, as instance attribute lookups are frequent.

如果您尝试从Python代码访问instance.__dict__,则将调用描述符;否则,将调用该描述符.它是一个数据描述符对象,因此在查看实例属性之前就将其调用.

If you try to access instance.__dict__ from Python code, then the descriptor is invoked; it is a data descriptor object so is invoked before instance attributes are even looked at.

这篇关于Python如何绕过普通属性查找以找到__dict__?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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