学python的人都知道,python中一切皆是对象,如class生成的对象是对象,class本身也是对象,int是对象,str是对象,dict是对象...。所以,我很好奇,python是怎样实现这些对象的?带着这份好奇,我决定去看看python的源码,毕竟源码才是满足自己好奇心最直接的方法。

  在object.h文件中,定义了两种数据结构PyObject和PyVarObject,代码如下:

 1 #define PyObject_HEAD                \
 2     Py_ssize_t ob_refcnt;               \
 3     struct _typeobject *ob_type;
 4
 5 #define PyObject_VAR_HEAD       \
 6     PyObject_HEAD                       \
 7     Py_ssize_t ob_size;
 8
 9 typedef struct _object {
10     PyObject_HEAD
11 } PyObject;
12
13 typedef struct {
14     PyObject_VAR_HEAD
15 } PyVarObject;

  这两种数据结构分别对应python的两种对象:固定长度对象和可变长度对象。python中的所有对象都属于这两种对象中的一种,如int,float是固定长度对象,list,str,dict是可变长度对象。从上面两种对象数据结构定义来看,可变长度对象和固定长度对象的头都是PyObject结构体,也就是说python中所有对象的开头都包含这个结构体,并且可以用PyObject *指针来访问任何对象,这种访问对象的方法在python的源码中随处可见。PyObject结构体包含两个成员,ob_refcnt和ob_type指针。ob_refcnt用来表示对象被引用的次数,当ob_refcnt == 0时,这个对象会被立即销毁;ob_type指针指向了一个_typeobject类型的结构体,表示对象所属的类型,也就是生成该对象的类型,这其实很类似于面向对象中类与实例的关系,PyObject是某个类的实例,ob_type表示这个类。但与面向对象不同的是,ob_type本身也是个对象,我们来看下_typeobject的定义:

 1 typedef struct _typeobject {
 2     PyObject_VAR_HEAD
 3     const char *tp_name; /*类型名 */
 4     Py_ssize_t tp_basicsize, tp_itemsize; /* 实例化对象的大小 */
 5
 6     /* 标准方法 */
 7
 8     destructor tp_dealloc;
 9     printfunc tp_print;
10     getattrfunc tp_getattr;
11     setattrfunc tp_setattr;
12     cmpfunc tp_compare;
13     reprfunc tp_repr;
14
15     /* 标准类(数值类,列表类,dict类)方法*/
16
17     PyNumberMethods *tp_as_number;
18     PySequenceMethods *tp_as_sequence;
19     PyMappingMethods *tp_as_mapping;
20
21     /* 其它标准方法*/
22
23     hashfunc tp_hash;
24     ternaryfunc tp_call;
25     reprfunc tp_str;
26     getattrofunc tp_getattro;
27     setattrofunc tp_setattro;
28     ...
29 } PyTypeObject;

  从上面定义来看,_typeobject的开头也包含了PyObject结构体,所以它也是一个对象,既然它也是一个对象,那么按照面向对象的理解,它又是谁来生成的呢?答案是所有PyTypeObject对象都是通过PyType_Type来生成的,包括PyType_Type本身,因为PyType_Type也是PyTypeObject对象,有点绕。PyType_Type的定义是通过将PyType_Type声明为全局静态变量实现的,具体如下:

 1 PyTypeObject PyType_Type = {
 2     PyVarObject_HEAD_INIT(&PyType_Type, 0)
 3     "type",                                     /* tp_name */
 4     sizeof(PyHeapTypeObject),                   /* tp_basicsize */
 5     sizeof(PyMemberDef),                        /* tp_itemsize */
 6     (destructor)type_dealloc,                   /* tp_dealloc */
 7     0,                                          /* tp_print */
 8     0,                                          /* tp_getattr */
 9     0,                                          /* tp_setattr */
10     0,                                  /* tp_compare */
11     (reprfunc)type_repr,                        /* tp_repr */
12     0,                                          /* tp_as_number */
13     0,                                          /* tp_as_sequence */
14     0,                                          /* tp_as_mapping */
15     (hashfunc)_Py_HashPointer,                  /* tp_hash */
16     (ternaryfunc)type_call,                     /* tp_call */
17     0,                                          /* tp_str */
18     (getattrofunc)type_getattro,                /* tp_getattro */
19     (setattrofunc)type_setattro,                /* tp_setattro */
20     0,                                          /* tp_as_buffer */
21     ...
22 }

  从PyType_Type定义来看,ob_type被初始化为它自己的地址,所以PyType_Type的类型就是自己。从python源码实现来看,所有PyTypeObject的ob_type都会指向PyType_Type对象,所以PyType_Type是所有类型的类型,称之为元类。python中定义了很多内建的类型对象,如PyInt_Type (int类型),PyStr_Type (str类型),PyDict_Type(dict类型) 类型对象,下面看下PyInt_Type类型的定义:

 1 PyTypeObject PyInt_Type = {
 2     PyVarObject_HEAD_INIT(&PyType_Type, 0)
 3     "int",
 4     sizeof(PyIntObject),
 5     0,
 6     (destructor)int_dealloc,                    /* tp_dealloc */
 7     (printfunc)int_print,                       /* tp_print */
 8     0,                                          /* tp_getattr */
 9     0,                                          /* tp_setattr */
10     (cmpfunc)int_compare,                       /* tp_compare */
11     (reprfunc)int_to_decimal_string,            /* tp_repr */
12     &int_as_number,                             /* tp_as_number */
13     0,                                          /* tp_as_sequence */
14     0,                                          /* tp_as_mapping */
15     (hashfunc)int_hash,                         /* tp_hash */
16     0,                                          /* tp_call */
17     ...
18 };

  从PyInt_Type定义来看,它主要包含了int数据类型相关的方法。PyInt_Type 类型对象的初始化和PyType_Type 类型类似,PyInt_Type类型的定义也是通过全局静态变量的方式实现的,除了PyInt_Type了下,所有python内建类型都是以这种方式定义的。这些类型产生的对象都会共享这些类型对象,包括这些类型定义的方法。

  在python中,怎样查看对象的类型呢?有两种方法,一种是直接type:

1 >>> x = 1
2 >>> type(x)
3 <type 'int'>

  另一种是通过对象的__class__属性:

1 >>> x = 1
2 >>> type(x)
3 <type 'int'>
4 >>> x.__class__
5 <type 'int'>

  现在来看看int,str,dict这些类型的类型:

1 <type 'int'>
2 >>> type(int)
3 <type 'type'>
4 >>> type(str)
5 <type 'type'>
6 >>> type(dict)
7 <type 'type'>
8 >>> type(type)
9 <type 'type'>

  从这个输出来看,int,str,dict这些类型的类型都是type,这也印证了前面说的,所有类型都是通过元类type生成的。

转载于:https://www.cnblogs.com/chengxuyuancc/p/5402020.html

读python源码--对象模型相关推荐

  1. 读Python源码(三)Python列表的表示

    简介: 在家过了个春节快不知道自己是干啥的了:),今天收拾一下心情继续读一下python的源码.这一节打算探究一下Python中列表是如何实现的. 1.Python列表创建 首先来到listobjec ...

  2. Python源码怎么读,听听顶级爬虫工程师的建议

    图源来自Miguel Á. Padriñán 如何高效调试Python程序?Python内部的架构设计是怎样的?多业务类型的复杂系统中,Python语言的定位是? -- 以上问题,单从研究Python ...

  3. python源码剖析 豆瓣_在数据分析师的分析中豆瓣的书那些值得读

    最近总是有人问我有什么书好推荐看看,特烦.但是看到那么多人问,看来挺多人有这个需求,便想了一下,如何通过数据分析找到值得看的书.通过爬取某个标签例如产品,运营获取对应已经打了标签的书,获取书对应的评分 ...

  4. python源代码-Python 源码深度剖析

    课程亮点 了解Python运行机制和设计思想: 熟悉背后的数据结构和算法原理: 结合工程实际,掌握高效程序设计之道: 高级面试知识点,求职更自信: 大量图表辅助学习,难点知识轻松拿下. 课程简介 能用 ...

  5. 《Python源码剖析》读书笔记

    <Python源码剖析>电子书下载 http://download.csdn.net/detail/xiarendeniao/5130403 Python源码在官网有下载链接,用ctags ...

  6. 读Zepto源码之操作DOM

    2019独角兽企业重金招聘Python工程师标准>>> 这篇依然是跟 dom 相关的方法,侧重点是操作 dom 的方法. 读Zepto源码系列文章已经放到了github上,欢迎sta ...

  7. 【Python基础】加密你的Python源码顺便再打个包如何?

    本篇为专属于"交通科研Lab"志愿者系列推文活动,为大家带来交通高校硕博们原创推文.为作者点赞,欢迎大家关注交流!!! 点击蓝字 关注我们 成为一个智慧.快乐和富有的人. --王宇 ...

  8. Python发展的新时代—冯大辉先生谈《Python源码剖析》

    Python 3.0 beta 1终于在 6 月 18 号发布了,依照Python一贯主张的简洁,标准,统一精神,Beta版的新特性让我们惊喜的发现,Python正如我们所期望的那样已经进入了一个蓬勃 ...

  9. 读zepto源码之工具函数

    2019独角兽企业重金招聘Python工程师标准>>> Zepto 提供了丰富的工具函数,下面来一一解读. 源码版本 本文阅读的源码为 zepto1.2.0 $.extend $.e ...

  10. Python源码学习笔记:Python程序执行过程与字节码

    Python程序执行过程与字节码 注:本篇是根据教程学习记录的笔记,部分内容与教程是相同的,因为转载需要填链接,但是没有,所以填的原创,如果侵权会直接删除. 问题: 我们每天都要编写一些Python程 ...

最新文章

  1. JavaScript原生代码处理JSON的一些高频次方法合集
  2. 在GHOST的WINXPSP2安装SQL SERVER2000个人版时出现“以前的某个程序安装已在安装计算机上创建挂起的文件操作。运行安装之前,必须重新启动计算机。”错误的解决方法...
  3. spark 持久化 mysql_Spark读取数据库(Mysql)的四种方式讲解
  4. win10 uwp 通知列表
  5. 146. LRU Cache
  6. Flink Kafka consumer的消费策略配置
  7. Google C++编程风格指南(一):背景
  8. java 动态转换器,Java 编程的动态性,第 5 部分: 动态转换类
  9. 模型训练太慢?显存不够用?这个算法让你的GPU老树开新花
  10. 如何设置的单位为m_如何将视频设置为网页背景
  11. Oracle树查询(查询所有子节点,父节点等等)_转载
  12. Axure RP一个专业的高速原型设计工具
  13. 宾得k5ii_K5--K5II---K5IIs,该选哪个?(喜欢宾得机的摄友)各抒己见。
  14. [Android] 选项卡组件TabHost
  15. 友盟分享微信图标显示成圆形
  16. 引入组件时的错误:Module not found: Error: Can‘t resolve ‘@/pages/Search‘
  17. matplotlib之2010-2017年各季度国民生产总值散点图
  18. python二级操作题评分方法_第二卷讲解Python语言计算机等级考试二级操作题
  19. python打印小票_购物小票——Python字符串格式化练习
  20. Luogu 1880 合并石子

热门文章

  1. Html图片懒加载动画,带加载进度的Web图片懒加载组件Lazyload
  2. jstack简单使用,定位死循环、线程阻塞、死锁等问题
  3. spring mvc 上传文件
  4. 查看系统端口是否被占用
  5. ORACLE 口令失效问题【转】
  6. 2与27日 双目视觉系统,相机标定,矫正,匹配(特征,稠密),特征提取的方法,得到视差图
  7. 比 matplotlib 效率高十倍的数据可视化神器
  8. Javascript实现完美继承
  9. 1月16日学习内容整理:存储库MongoDB之pymongo模块
  10. Java多线程(六)线程池