类的 __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__的更多相关文章

  1. python进阶_浅谈面向对象进阶

    python进阶_浅谈面向对象进阶 学了面向对象三大特性继承,多态,封装.今天我们看看面向对象的一些进阶内容,反射和一些类的内置函数. 一.isinstance和issubclass  class F ...

  2. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

  3. 浅谈 LayoutInflater

    浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...

  4. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  5. 浅谈SQL注入风险 - 一个Login拿下Server

    前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...

  6. 浅谈WebService的版本兼容性设计

    在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...

  7. 浅谈angular2+ionic2

    浅谈angular2+ionic2   前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别.   1. 项目所用:angular2+ionic2 ...

  8. iOS开发之浅谈MVVM的架构设计与团队协作

    今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...

  9. Linux特殊符号浅谈

    Linux特殊字符浅谈 我们经常跟键盘上面那些特殊符号比如(?.!.~...)打交道,其实在Linux有其独特的含义,大致可以分为三类:Linux特殊符号.通配符.正则表达式. Linux特殊符号又可 ...

随机推荐

  1. 在 vSphere 5.x/6.0 中配置 Network Dump Collector 服务 (2002954)

    vmware KB: https://kb.vmware.com/s/article/2002954?lang=zh_CN 重点配置命令: 使用 vSphere Client 连接到 vCenter ...

  2. 封装简单的mvc框架

    MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式. MVC把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller). PH ...

  3. 成为技术领导者笔记--领导的MOI模型

    一. 想让周围环境发生变化,环境必须包含三个条件: M:激励(Motivation)---有奖品或有困难,这样才对相关人员有推动力或吸引力. O:组织(organization)---利用现有的组织结 ...

  4. 字符串,元组,列表; 切片&range

    总结:字符串: "" 组成元组: () 组成列表: [] 组成 切片 中括号冒号: [5: 0: -2] # print(s2[5:0:-2]) 此步长为-2,则从右往左取, 则a ...

  5. codeforces 17D Notepad

    codeforces 17D Notepad 题意 题解 TBD 更新模板(phi.欧拉降幂) 代码 #include<bits/stdc++.h> using namespace std ...

  6. 两周以来的学习成果&遇到的问题及解决:

    1.学习java的基本内容,看慕课网上的java入门三季,与韩顺平老师的java视频 刚开始是看韩顺平老师的视频,边看边实战,内容很细,也很快熟练,但是进度太慢.后来就先看了慕课网上的java 入门的 ...

  7. Result工具类

    使用ajax请求访问时,可以用此工具类作为返回对象,也方便统一代码规范 package com.ujia.entity; import java.io.Serializable; public cla ...

  8. 那些不明不白的$符号设计--Sass和Emmet,变量设计原理相通

    以前看到php变量的定义,直接使用$符号开始,怎么看都不习惯.后来呀,在使用Emmet的过程中,又接触到了$符号.今天,在学习Sass的过程种,再一次接触到$符号,兴致所致,不由得想写一篇,对比一下搞 ...

  9. virtualbox+vagrant学习-2(command cli)-12-vagrant Provision命令

    Provision 格式: vagrant provision [vm-name] [--provision-with x,y,z] 针对正在运行的vagrant托管计算机运行任何配置预配置程序. u ...

  10. django 表结构

    django 表结构 一:查看orm写的sq语句:如果对某个语句不清楚的话可以调用queryset的的query方法来查看sql. 1 obj=Hostinfo.objects.filter(id=v ...