我了解__dict__
中的obj.__dict__
是type(obj)
的描述符属性,因此obj.__dict__
的查找为type(obj).__dict__['__dict__'].__get__(obj)
。
来自https://stackoverflow.com/a/46576009
很有可能说
__dict__
必须是描述符,因为 将其作为__dict__
条目实现将需要您找到__dict__
之后才能找到__dict__
,但 Python已经存在 在查找时绕过常规属性查找以查找__dict__
其他属性,因此不像最初那样引人注目 声音。如果描述符被替换为'__dict__'
键 每个__dict__
,__dict__
仍然可以找到。
" Python如何绕过正常的属性查找来查找__dict__
"? "正常属性查找"意思?
根据链接中引用的上下文,我不认为当作者写这篇文章时,他提到obj.__dict__
的查找是type(obj).__dict__['__dict__'].__get__(obj)
。
答案 0 :(得分:3)
通过调用__getattribute__
hook或更准确地说C-API tp_getattro
slot来完成正常的属性查找。此默认实现位于PyObject_GenericGetAttr
C-API function。
PyObject_GenericGetAttr
的工作是调用描述符(如果它们存在),并查看实例__dict__
。实际上,是一个__dict__
描述符,但__getattribute__
直接访问实例内存结构中的__dict__
插槽更快,那就是the actual implementation做了什么:
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;
}
}
请注意内联_PyObject_GetDictPtr
评论;这是性能优化,因为实例属性查找很频繁。
如果您尝试从Python代码访问instance.__dict__
,则会调用描述符;它是一个数据描述符对象,因此在查看实例属性之前调用它。