1 前言

最近在读《python源码剖析》一书,收获颇丰。 虽然此书成书已久,书中所讲与如今的实现已有颇多不同, 可是程序框架并未有太多改动,再辅以python官网文档, 仍可以借此一窥python源码。

在依据此书参研过程中,所获颇丰,淋漓尽致之余突生记录心得之想,因此开始写这篇博客。 如果我懒癌没发作,那么应该会有若干后续博客,或许会涉及python大部分内置类型的剖析乃至其他; 若不幸懒癌发作,这一篇博客也足以记录足够的知识点以便以后快速想起对象模型相关。

文中代码的依据均是 Python 3.4.2 的源代码。

2 对象模型概览

  • 本节内容出自Include/object.h

2.1 PyObject

Python中的对象有一些共有的性质,这些性质被提取出来放在一个固定的结构中:

typedef struct _object {_PyObject_HEAD_EXTRAPy_ssize_t ob_refcnt;struct _typeobject *ob_type;
} PyObject;
/* _PyObject_HEAD_EXTRA是一个宏。* 在未定义Py_TRACE_REFS宏时,该宏为空,因此忽略可以忽略该部分*/

PyObject的成员很简单,一个用来表示引用数量的ob_refcnt (注:python实现了引用计数垃圾回收,这个引用数量就是用于这个的。 那个Py_ssize_t可以认为是一个long,总之是一个整形), 一个用来表示对象类型的ob_type。关于对象类型的内容会在后文详细提到。

这个就是python里所有对象在解释器中的通用表示结构。 不仅如此,python的C API中许多函数也接受PyObject*类型的参数。

2.2 PyVarObject

python中,有定长的对象也有变长的对象(不过在python3.4中,关于变长和定长有一些不符合常识的设定,这个以后再说), 像list就是典型的变长对象,它的大小取决于元素个数,是无法预知的。

变长对象也有一些通用特性,这些特性被提取出来放在了下列数据结构中:

typedef struct {PyObject ob_base;Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;

其中的ob_size是变长对象中元素的个数,而不是该对象占用的实际空间大小。 而通过包含PyObject类型的成员,实际上手动实现了一种简单的继承。 为了更清楚的看到这种继承关系以及它在对象模型中的作用, 在后文会给出一个继承关系的图。

2.3 PyTypeObejct

PyTypeObejct是用来表示对象类型的数据结构,其定义如下:(已省略大部分定义以节约空间)

typedef struct _typeobject {PyObject_VAR_HEAD /* 一个宏,展开后为:PyVarObject ob_base; */const char *tp_name; /* For printing, in format "<module>.<name>" */Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation *//* Methods to implement standard operations */destructor tp_dealloc;printfunc tp_print;/* Method suites for standard classes */PyNumberMethods *tp_as_number;PySequenceMethods *tp_as_sequence;PyMappingMethods *tp_as_mapping;/* ... */
} PyTypeObject;

PyTypeObject结构包含了一个类型需要的各类数据,以上文代码列出的成员为例:

  • ob_base,它的ob_base成员(也就是ob_base.ob_base)就是代表某一个类型的对象(没错,每一个类型也是一个特殊的对象)
  • tp_basicsize, tp_itemsize:和该类型对象大小有关
  • tp_name是该类型的名字
  • tp_dealloc是这个类型的析构函数
  • tp_as_number:作为数值类型的函数族,比如加减乘除之类

上文的代码中省略了大量的函数指针,那些函数指针都是一些类型需要或可能具有的操作。

每一个类型都有一个独立的PyTypeObject类型的变量。 但是注意,由于PyTypeObject也简介包含了一个PyObject类型的成员, 而该成员需要指向某一个PyTypeObject类型的变量, 但显然,无法指向此PyTypeObject。以int类型为例,若int类型所指向的PyTypeObject变量是自身的话, 那么代表int类型的类型就是int类型本身。 但这样首先与直觉不符,int类型作为 一个类型 和int类型的对象作为 一个对象 拥有相同的类型 本身就是很反直觉的。或许有少数类型可以做到这一点,但int类型却明显不在此列, int这个类型和int对象的性质和操作千差万别,绝不可能是同一类型。 其次,和运行结果也不相符,如果在python中运行type(int),并不会显示int,而是显示type。

因此,为了解决这个问题,python中内建了一个元类型PyType_Type(也就是运行type(int)结果中type的来源), PyType_Type是内置类型的类型,它本身的类型也是它自身。

2.4 总结

此时,python对象模型中最基础的三个数据结构已经介绍完了,可是它们之间的关系、 它们和python中类型、对象的关系还不是很明确。 这里上图一张:

如图,不管是PyTypeObject也好,还是PyVarObject也好,都包含了PyObject类型的成员, 因通过这种方法手动实现了继承。

同时,每一个存在的PyObject类型的实例都对应了一个单独的对象, 因此即使是PyTypeObject这样用来表示类型的东西最后也会对应到一个对象上, 只不过这个对象十分特殊。

最后,再用python中的一个简单的int类型的对象来说明对象模型的结构。 以 a = 10 为例:

其中的PyLong_Type是在python3.0以后int类型的结构。 本图有一些不恰当的地方,10这个对象的内容应该更复杂, 它应该是继承自PyObject的一个专门的类型的实例。 不过为了简便,这里就用这种不规范的方法表示了。

转载于:https://www.cnblogs.com/w0mTea/p/4282917.html

CPython对象模型:基础相关推荐

  1. CPython对象模型:整型

    前一篇:CPython对象模型:基础 程序中,最常用的数据类型之一就是整型了. 本篇博文记录的就是研究整型过程中的一些心得. 1 PyLongObject 1.1 版本之别 在python2.x中,整 ...

  2. CPython对象模型:string(留坑待填)

    在python3中,移除了2中的byte string,string变的和2中的unicode类似.所以在python3中烦人的编码问题会少不少. 在准备动手写这一篇的时候,查了不少资料,结果不小心发 ...

  3. Entity Framework 4 in Action读书笔记——第三章:查询对象模型基础(1)

    本章要点: 1.EF查询技术. 2.捕捉生成的SQL. 3.深入理解EF查询引擎. 4.常见的查询陷阱. 一.查询引擎入口点 对象服务层最重要的类是ObjectContext.在你的代码中它是最有用的 ...

  4. Python vs Cpython

    本文翻译自:Python vs Cpython What's all this fuss about Python and CPython (Jython,IronPython) , I don't ...

  5. 绕开“陷阱“,阿里专家带你深入理解C++对象模型的特殊之处

    摘要:本文介绍了C++对象模型的特殊之处,包括与C兼容的朴素模型,以及能支持多态的虚表模型,同时还带大家了解了构造函数与析构函数相关的一些特性与陷阱.这些内容能够帮助大家更好地学习和使用C++. 数十 ...

  6. p3.第一章 Python基础入门 -- Python编程基本概念 (三)

    1.2.2 Python语言 1.2.2.1 Python发展 1989年圣诞节期间,为了打发无聊的时间,荷兰人Guido van Rossum(吉多·范罗苏姆)(数学.计算机双硕士,2005年加入G ...

  7. python语言只采用解释一种翻译方式对吗_python-guide翻译

    python看了也有一段时间了,但是由于不常用到,所以经常看了忘忘了又看,这次决定做个记录顺便梳理一下学过的内容. 查资料时恰好在github上看到这个项目https://github.com/jia ...

  8. 一致的数据访问技术ADO/OLE DB

    Microsoft新近推出的UDA(Universal Data Access,一致数据访 问技术)为关系型或非关系型数据访问提供了一致的访问接口,为企业 级Intranet应用多层软件结构提供了数据 ...

  9. python初级_python--的初级了解

    python的简史 • 1989年,Guido(龟叔)python. • 1990年, 发布python的第一个版本; • 2001年发布python2.0版本; • 2010年获年度Tiobe编程语 ...

最新文章

  1. shiro原理_java:shiro高级篇——1
  2. 使用 HttpLib 来访问 Web 服务
  3. JDK源码学习之Arraylist与LinkedList
  4. 使用CrossOver安装第三方软件
  5. java hibernate注解_Hibernate注解方法使用总结
  6. 拓端tecdat|R语言分析股市相关结构:用回归估计股票尾部相关性(相依性、依赖性)
  7. 分享“消防图纸”识图方法,让你一眼秒懂!
  8. intel 9260AC网卡修改成Killer 1550
  9. java jshell 命令
  10. 海洋测绘 知识点 详细
  11. My console windows won't go away
  12. Canon F-789sga 计算器
  13. PS填充颜色边缘模糊
  14. fgets和fputs的使用
  15. 无向图的关联矩阵JAVA_图的矩阵表示无向图及有向图的关联矩阵.doc
  16. 第三方物流学习(五)
  17. HDU 献给杭电五十周年校庆的礼物
  18. Superset从入门到真香
  19. 计算机网络(第八版)谢希仁编著 笔记
  20. 伺服电机与步进电机的区别

热门文章

  1. python2.7教程-python2.7学习笔记——菜鸟教程
  2. 计算机组成原理—基本概念(不基础的部分)
  3. p73_万维网和HTTP协议
  4. 汉明码---存储器校验(简单易懂详解)
  5. Codeforces Round #493 (Div. 2):C. Convert to Ones
  6. bzoj 3450: Tyvj1952 Easy(概率DP)
  7. 1633: [Usaco2007 Feb]The Cow Lexicon 牛的词典(DP)
  8. bzoj 1202: [HNOI2005]狡猾的商人(带权并查集)
  9. rand()与srand()的简单应用(随机数)
  10. matlab二进制十进制十六进制和任意进制之间的转换