阅读条件:
C语言基础, Python爱好者
<!--more-->
序
本系列是阅读Python源码剖析的读书笔记.
所有Python的语言魔法都有一个朴素的解释.
近一年以来,一直在使用Python完成项目,时常惊叹于Python语法的简洁优雅.PEP 20 The Zen of Python描述了Python的指导原则.
我也读过类似Effective Python:59个方法和Solid Python:91个建议这样的书籍,并且尝试在实际项目使用学习到的Tips.但是总有些隔靴搔痒的意思.
对于一些语言特性,比如元类,装饰器,生成器,弱类型等,总是有一种雾里看花的感觉.惊叹于这些语言特性的魔力,但是要看穿魔法的迷雾还是需要深入到Python的源码实现中去.
我们都知道原始Python语言本身是用C语言实现的.本系列就是阅读Python源码剖析后的读书笔记.
我的读书笔记主要基于自己已有的知识,蜻蜓点水般的记录了自己的总结和收获.更多精彩的内容还是要到书中去捡拾.
前言
Python实现主要分为3个主要部分:
- 模块和库
- Python虚拟机
- 运行时环境: Python对象模型, 内存分配, 运行状态
我们同样遵循书中的提纲,本篇主要介绍Python对象模型.
即使接触Python不久的同学可能也知道,Python中一切都是对象.整数是整数对象,字符串是字符串对象,函数是函数对象甚至类的定义本身也是一个对象.
那么在源码层面,这种一切都是对象的机制是怎么做到的呢?这也是本文的核心问题:
如何用C语言实现不同对象的对象模型?甚至对外暴露统一的接口
源码目录与结构
书中源码是Python 2.5.0,涉及到的主要代码在Include
和Objects
目录中.前者是头文件声明,后者根据不同的对象在不同的文件中实现了对应的方法.
Python对象
初识
在Python源码中,我们经常看到的一个结构体就是PyObject
,似乎每个Python中的对象都可以用这个结构体来描述.下面我们就来看下这个结构体的定义:
源码还是解释的比较清楚的,PyObject
仅仅包含了一个叫做PyObject_HEAD
的东西.顾名思义,这大概是表示一个Python对象的头部.
我们将上面的代码合并,看看头部中到底有哪些东西.
可以看到,首先是引用计数,不用想这一定是和内存回收有关系的,我们先跳过.其次,是一个指向类型结构体的指针.
对象类型
接着我们来看看struct _typeobject
是怎么一回事.
这段代码还是比较长的,我们大致看看.也能猜出其中不少的含义.
其中通过tp_name
描述了类型的名称,通过tp_basicsize
和tp_itemsize
描述了对象的大小.
后面还有一系列的对象方法.
对象数据
我们在前面已经看到对象的类型,方法都已经有了.那么对象本身的数据呢?我们通过最简单的一个对象类型来看一看.
深入一层,我们来看PyInt_Type
的定义:
可以看到对于Int类型的对象而言,数据就跟在PyObject_HEAD
的后面.而在类型信息中,则规定它的各种对应操作.
其他
缓冲池
在常见的内建对象类型中,包括整数,字符串,列表,字典中,都使用了类似的缓存机制. 本质上,就是希望尽可能少的使用到系统调用,同时尽可能高效使用内存.
模拟Small Python
作者提供了一段非常简洁的C++代码,模拟了简单的Python行为.我没有找到原始代码,但是在github上我找到一份.
我将部分warning修复后,也放到了GitHub上,这是本文最有价值的部分.
总结
本文描述了Python的对象模型的基础.Python对象模型是通过C来实现的,那么如何使用C语言实现面向对象的语言.在我们的示例代码中给出了范例.