浅谈__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__的更多相关文章
- python进阶_浅谈面向对象进阶
python进阶_浅谈面向对象进阶 学了面向对象三大特性继承,多态,封装.今天我们看看面向对象的一些进阶内容,反射和一些类的内置函数. 一.isinstance和issubclass class F ...
- 浅谈 Fragment 生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...
- 浅谈 LayoutInflater
浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈SQL注入风险 - 一个Login拿下Server
前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...
- 浅谈WebService的版本兼容性设计
在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...
- 浅谈angular2+ionic2
浅谈angular2+ionic2 前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别. 1. 项目所用:angular2+ionic2 ...
- iOS开发之浅谈MVVM的架构设计与团队协作
今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
- Linux特殊符号浅谈
Linux特殊字符浅谈 我们经常跟键盘上面那些特殊符号比如(?.!.~...)打交道,其实在Linux有其独特的含义,大致可以分为三类:Linux特殊符号.通配符.正则表达式. Linux特殊符号又可 ...
随机推荐
- Linux uname命令详解
uname常见命令参数 -a, --all print all information, in the following order, except omit -p and -i if unknow ...
- PHP解决网站大数据大流量与高并发
1:硬件方面 普通的一个p4的服务器每天最多能支持10万左右的IP,如果访问量超过10W那么需要专用的服务器才能解决,如果硬件不给力软件怎么优化都是于事无补的.主要影响服务器的速度 有:网络-硬盘读写 ...
- Ubuntn系统(虚拟机)忘记密码的解决方法
1.重启ubuntu系统,开机时长按shift按键进入GRUB菜单,选择第二个高级选项,enter键进入.如下图: 2.在高级选择中选择Recovery mode模式,键盘按“e”键进入编辑模式.如下 ...
- November 28th 2016 Week 49th Monday
You only live once, but if you do it right, once is enough. 年华不虚度,一生也足矣. One today can win two tomor ...
- JDK源码学习LinkedList
LinkedList是List接口的子类,它底层数据结构是双向循环链表.LinkedList还实现了Deque接口(double-end-queue双端队列,线性collection,支持在两端插入和 ...
- 1503. [NOI2004]郁闷的出纳员【平衡树-splay】
Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的 工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经 ...
- P4053 [JSOI2007]建筑抢修
题目描述 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建 ...
- Python自动化之高级语法单例模式
方法1 共享属性;所谓单例就是所有引用(实例.对象)拥有相同的状态(属性)和行为(方法) 同一个类的所有实例天然拥有相同的行为(方法), 只需要保证同一个类的所有实例具有相同的状态(属性)即可 所有实 ...
- servlet使用
一.使用IDEAL创建项目 1) 2) 3) 4) 5) 6) 7) 8) 9) 二.路径介绍: 配置文件: servlet配置文件: package ser_Test; import javax.s ...
- 命令行编译执行java
命令行编译运行java程序 使用命令 javac进行编译 和 java进行执行. javac 后面跟着的是java文件的文件名,例如 HelloWorld.java. 该命令用于将 java 源文件编 ...