最近陷入咸鱼状态(虽然一直都是)。python3.6也出来了,想到自己还没有读过python的源代码,想着狠下心来读一下看看。然而水平实在有限,不敢说有彻底读懂,只能说是对源码的阅读和个人理解。欢迎各位朋友批评指正。

python 源码指的一般是CPython。CPython即用C语言实现Python及其解释器(JIT编译器),Jython是用Java语言来实现,Pypy是用Python来实现(准确说是个Python子集)。

我们可以在cpython的github项目的branch中下载到Cpython各个版本的源代码。

此处下载下来的源码包含有下面几个文件夹。^1

  • Doc:包含python的文档
  • Grammar:包含python语法分析器
  • Include:包含python的C头文件
  • Lib:python的基础库函数
  • Mac:包含在Mac上使用的特殊文件
  • Misc:包含不适合其他地方的文件,只是具有历史意义。
  • Modules:python用到的C的模块
  • Objects:多种内置类型的源文件
  • Parser:python的分词器。
  • PC:包含一些旧的PC的py端口,以及所有PC特有的python源文件
  • PCbuilde:用于在Windows NT上安装python。
  • Programs:二进制可执行文件的源代码
  • Python:主要Python库的其他源文件
  • Tools:包含一些在构建或扩展Python时有用的Python程序。包括pdb等

首先看Include文件夹。Python实现了哪些东西,首先是从object.h这个文件开始看起。106行:

1
2
3
4
5
6
7
8
9
10
/* Nothing is actually declared to be a PyObject, but every pointer to
* a Python object can be cast to a PyObject*. This is inheritance built
* by hand. Similarly every pointer to a variable-size Python object can,
* in addition, be cast to PyVarObject*.
*/
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;

注释的意思是:没有什么是确切被声明为PyObject的但是任何指向python对象的指针都可以被转换为一个PyObject指针。这时手动制造的派生。同样的每一个指向可变大小的Python对象也能转换为PyVarObject指针。

这就是一个python对象的基本内容,里面包含了

  • _PyObject_HEAD_EXTRA,定义了指向内存堆中存活的对象的前驱后继的双向链表的结点。
1
2
3
4
/* Define pointers to support a doubly-linked list of all live heap objects. */
#define _PyObject_HEAD_EXTRA \
struct _object *_ob_next; \
struct _object *_ob_prev;
  • ob_refcnt 是一个引用计数器,其类型Py_ssize_t实际是一个64位的int。
  • *ob_type 是一个指向类型对象的指针。类型对象指示函数的类型。在python使用type()函数就能找到当前对象的类型。

上面注释还提到的PyVarObject,其源代码就在PyObject下面:

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

其包含了一个PyObject和一个指示数量的ob_size。

_typeobject

关于我们之前看到的指示对象的类型的TypeObject,实际上是一个类型的对象,也是由PyObject来表示的一个类。他的定义在object.h的大概346行:

1
2
3
4
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<module>.<name>" */
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

定义的第一行指示了一个PyObject_VAR_HEAD,这实际上是一个
PyVarObject的宏(#define PyObject_VAR_HEAD PyVarObject ob_base;)

之后的两行指示的是模块用于打印的名称和用于分配内存的大小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
    /* Methods to implement standard operations */

destructor tp_dealloc;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
or tp_reserved (Python 3) */
reprfunc tp_repr;

/* Method suites for standard classes */

PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;

/* More standard operations (here for binary compatibility) */

hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;

/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer;

/* Flags to define presence of optional/expanded features */
unsigned long tp_flags;

const char *tp_doc; /* Documentation string */

/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;

/* delete references to contained objects */
inquiry tp_clear;

/* Assigned meaning in release 2.1 */
/* rich comparisons */
richcmpfunc tp_richcompare;

/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;

/* Iterators */
getiterfunc tp_iter;
iternextfunc tp_iternext;

/* Attribute descriptor and subclassing stuff */
struct PyMethodDef *tp_methods;
struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
struct _typeobject *tp_base;
PyObject *tp_dict;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
Py_ssize_t tp_dictoffset;
initproc tp_init;
allocfunc tp_alloc;
newfunc tp_new;
freefunc tp_free; /* Low-level free-memory routine */
inquiry tp_is_gc; /* For PyObject_IS_GC */
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
PyObject *tp_cache;
PyObject *tp_subclasses;
PyObject *tp_weaklist;
destructor tp_del;

/* Type attribute cache version tag. Added in version 2.6 */
unsigned int tp_version_tag;

destructor tp_finalize;

#ifdef COUNT_ALLOCS
/* these must be last and never explicitly initialized */
Py_ssize_t tp_allocs;
Py_ssize_t tp_frees;
Py_ssize_t tp_maxalloc;
struct _typeobject *tp_prev;
struct _typeobject *tp_next;
#endif
} PyTypeObject;
#endif

接着给出了一些标准操作的函数接口,包括了在python命令行输入dir(object)所能看到的几乎全部,这都是需要实现的接口。

这个文件其它的部分大多都是一些宏定义的字段。(实际上整个文件夹都是这样)

这一部分暂时看到这里了,下次看一个别的文件。咸鱼也需要一点时间发酵一下别的。