Python源码分析(三): 再次探讨 Python 中的类型与对象
源码面前, 毫无秘密 --- 鲁迅(bushi
我们知道 Python 是一门面向对象的脚本语言, 在编程语言中, 一种是自顶向下, 直接从数学开始推导出程序, 这基于邱奇的lambda演算, 这就是函数式编程。另一种是自底向上, 这基于图灵的理论,从计算机运行原理和底层汇编出发逐步封装使得问题变得更简单,运用面向对象编程来管理我们的状态。而 Python 就是这样一门简洁的面向对象语言(当然还有 Ruby), Python is programmer's best friend!
在 Python 的世界一切皆对象,不论是整数,还是字符串,甚至连类型、函数等都是一种对象。
我们再来看看对象的最基本形态 -- PyObject 结构体的定义:

类型对象也是对象
我们来看看 _typeobject 的定义, 这个结构体里面定义了类型名称, 类型支持的操作与内存分配的操作:
我们现在就从 PyObject 开始组合与封装出复杂的对象
PyVarObject可变长对象
我们看到 PyVarObject 里面包括了 PyObject (没错, 这就是用 c 语言实现继承和多态的方法), 而且还新增了一个 ob_size 的属性来记录当前的长度:

有了可变长对象, 我们在 Objects/typeobject.c 中看到 Python 会在运行时创建一个 PyType_Type 的对象:
实际上, Python中的类型对象最终都会引用到PyType_Type中, 下面是一个整数的类型对象在运行时结构体的状态:

所以我们可以得出结论:PyType_Type
在类型机制中至关重要,所有用户自定义 class
所 对应的 PyTypeObject
对象都是通过 PyType_Type
创建的!, 并且 PyType_Type 也是一个可变长对象,这再次体现出了 Python 动态语言的特性。
从 PyTypeObject 到其它对象类型
我们来看看 PyLong_Type 在运行时创建的源码:
我们看到 PyLong_Type 就是一个 PyTypeObject 类型对象。再来看看源码中经常出现的PyVarObject_HEAD_INIT宏:
这个宏的作用初始化 PyTypeObject 的 PyObject 部分 (ob_refcnt 初始化为 1, ob_type 指向 PyType_Type, 可变对象的 size 为 1)。
接下来打算分析一波 dict, set, list 等数据类型的实现, 再深入研究一下 VM internal 中的对象, 顺便复习一下算法和数据结构, 并且学习一下龟叔写代码的风格(只是希望能模仿一下)。