浅谈__dict__
Posted reboot51
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈__dict__相关的知识,希望对你有一定的参考价值。
类的 __dict__
先看一个例子:
> class A(object): pass > ... > A.__dict__ dict_proxy({‘__dict__‘: <attribute ‘__dict__‘ of ‘A‘ objects>, ‘__module__‘: ‘__main__‘, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘A‘ objects>, ‘__doc__‘: None})
发现 dict 是一个 dict_proxy 类型,为何不是一个简单的 python dict 呢?跟一下代码看一下:
case LOAD_ATTR: w = GETITEM(names, oparg); v = TOP(); x = PyObject_GetAttr(v, w); Py_DECREF(v); SET_TOP(x); if (x != NULL) continue; break;
获取变量会执行 LOAD_ATTR 的机器码,对于 A 类会走到如下函数:
# in typeobject.c static PyObject * type_getattro(PyTypeObject *type, PyObject *name) { ... meta_attribute = _PyType_Lookup(metatype, name); 【1】 if (meta_attribute != NULL) { meta_get = Py_TYPE(meta_attribute)->tp_descr_get; if (meta_get != NULL && PyDescr_IsData(meta_attribute)) { /* Data descriptors implement tp_descr_set to intercept * writes. Assume the attribute is not overridden in * type‘s tp_dict (and bases): call the descriptor now. */ return meta_get(meta_attribute, (PyObject *)type, (PyObject *)metatype); 【2】 } }
元类型:对于一个类的元类型是类型,对于类,会在类型中寻找 __dict __(参考1),返回一个描述符,并调用描述符 get 函数(参考2)。
最终会运行到下面的代码:
# in typeobject.c static PyObject * type_dict(PyTypeObject *type, void *context) { if (type->tp_dict == NULL) { Py_INCREF(Py_None); return Py_None; } return PyDictProxy_New(type->tp_dict); 【1】 }
【1】这里类型就是 A 类,所有就是读取 A 类的 tp_dict
实例的__dict__
读取一个类的实例的 __dict__ 会调用到如下方法:
# in object.c PyObject * _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) { .... descr = _PyType_Lookup(tp, name); 【1】 }
这里 tp 就是 A 类,因此我们需要在 A 类的 tp dict 寻找 _dict__ 变量,ok,使用下面的方式看一下:
> A.__dict__["__dict__"] <attribute ‘__dict__‘ of ‘A‘ objects> > type(A.__dict__["__dict__"]) <type ‘getset_descriptor‘>
这样会调用到对应的描述符
# in typeobject.c static PyObject * subtype_dict(PyObject *obj, void *context) { .... dictptr = _PyObject_GetDictPtr(obj); .... dict = *dictptr; .... return dict; }
上面的 obj 就是 A 类的实例。
模块的__dict__
模块的基本逻辑与实例相似,也是调用 _PyObject_GenericGetAttrWithDict 方法。
> type(a_p).__dict__[‘__dict__‘] <member ‘__dict__‘ of ‘module‘ objects> > type(type(a_p).__dict__[‘__dict__‘]) <type ‘member_descriptor‘>
会拿到模块的 __dict__,然后调用描述符对应的获取函数。
# in structmember.c PyObject * PyMember_GetOne(const char *addr, PyMemberDef *l) ....
作者:Whosemario
原文链接:http://t.cn/RgcAB5Y
以上是关于浅谈__dict__的主要内容,如果未能解决你的问题,请参考以下文章
functools.wraps 返回 dict 类型的 __dict__ 而不是 mappingproxy