Python源码剖析-Note1
1.Python 架构
-
1.1 文件组:
模块、库、自定义模块
-
1.2 核心
解析器
Scanner词法分析 -> Parser语法分析,建立AST(抽象语法树)
-> Compiler 生成指令集合,Python字节码(byte code) -> 由Code Evaluator(虚拟机)执行字节码 -
1.3 运行时环境
对象/类型系统 Object/Type structures
内存分配器 Memory Allocator
运行时状态信息 Current State of Python
2.Python的内建对象
-
2.1 关于对象
-
类型对象(整数类型,字符串类型)都是被静态初始化的
-
对象被创建后的内存中的大小是不可变的!
-
2.2 PyObject
-
只包含一个引用计数和一个类型指针(指向具体的结构信息)
/* PyObject_HEAD defines the initial segment of every PyObject. */ |
- 2.3 PyVarObject
- 对PyObject的扩展,可以理解为一个容器,比如对于一个string的实现,需要使用一个n * char的实现方式,因此需要一个字段存储长度。因此结构如下:
/* PyObject_VAR_HEAD defines the initial segment of all variable-size |
- 2.4 创建类型对象的方式
- 使用范型的API(AOL)
PyObject *intObj = PyObject_New(PyObject, &PyInt_Type); |
- 使用与类型相关的API(COL)
PyObject* intObj = PyInt_FromLong(20); |
- 2.5 对象的行为
- PyTypeObject包含大量函数指针,指明了其不同的对象的行为实现。
- 标准行为函数族:基础类型的函数,列表的函数族,字典用的函数族
PyNumberMethods *tp_as_number; |
2.6 类型的类型
- 对于用户自定义class所对应的PyTypeObject对象通过PyType_Type创建。
class A(object): |
python中被称为metaclass
int运行时类型关系:
int - ob_refent + ob_type
ob_type - PyInt_Type(ob_type)
PyInt_Type(ob_type) -> PyType_Type
PyInt_Type(tp_base) -> PyBaseObject_Type
2.7 多态的实现原理
所有的对象使用PyObject来存储,然后再对不同的对象类型执行不同的函数族,实现多态,如
// PyTypeObject PyInt_Type = { |
2.8 引用计数
- 增加和减少一个对象的引用计数
ob_refcnt <- Py_INCREF(op), Py_DECREF(op) |
- 类型对象是超越引用计数规则的,即永远不会析构,每个对象指向类型对象的指针不会被视为对类型对象的引用。
注意:当引数为0时,会调用其对应的析构函数,但这并不意味着一定会调用free,因为这样频繁的调用会导致性能不好,所以会采取将其放到内存池的作法。
2.9 对象分类:
- Fundamental对象:类型对象 type
- Numeric对象:数值对象 boolean, float, int
- Sequence对象:序列集合对象 list, tuple, string
- Mapping对象:对应C++中的map dict
- Internal对象:虚拟机运行时的内部使用对象 function, code, frame, module, method
3.Python中的整数对象
3.1 实现方式
- PyIntObject用于实现整数对象,不可变对象,即创建后就不能改变其值
引出问题? 非常频繁的创建和销毁Int对象将会导致性能问题
- 元信息:
PyTypeObject PyInt_Type = { |
- PyNumberMethods展示所有可选的操作信息
3.2 int_add的实现
- PyInt_AS_LONG vs PyInt_AsLong ,后者版本执行效率较慢,会有多方的检查
python中对于频繁执行的代码,都会提供函数和宏两个版本
- 默认情况下,返回一个新的PyIntObject, 当越界时将转为PyLong_Type的结果返回
static PyObject * |
3.3 PyIntObject的创建
- PyInt_FromString 与 PyInt_FromUnicode 最终都是调用PyInt_FromLong创建,适配器模式的设计模式
PyAPI_FUNC(PyObject *) PyInt_FromString(char*, char**, int); |
3.4 大整数与小整数
- 小整数: 默认是[-5,257]的范围,这些整数直接缓存在内存中,并存放其指针在small_ints的中。
// intobject.c |
- 大整数:提供一块内存空间,配置如下:
|
计算得出N_INTOBJECTS的值为24,对于一个64位指针使用8个字节来算
3.5 添加与删除
PyObject * |