我认识的python(2)

246 阅读3分钟

python原理

这篇文章主要是介绍python一些基本的原理。 python的整体架构可以分为三部分,分别是模块库管理,解释器还有运行时环境(包括对象/类型系统,内存分配器和运行时状态信息)。

模块库管理主要是python提供的大量模块,库以及用户自定义的python模块代码。

解释器是python代码运行的核心组件,首先解释器对文件进行Scanner词法分析,将一行行代码转换成token流,接下来Parser过程对应语法分析,针对Scanner的结果进行语法分析,生成AST语法树,Compile针对AST语法树的结果生成指令集合-字节码。最后code evaluator对字节码进行执行。

运行时环境包括了对象/类型系统,内存分配器和运行时状态信息。运行时状态信息是维护解释器在执行指令的不同状态之间切换的动作,类似一个有穷的状态机。内存分配器是用于管理python对象的创建,对内存的申请,针对malloc进行一层封装。对象/类型系统包含python内置的各种数据结构对象和用户自定义的各种类型和对象。

python整体结构

python对象/类型系统

python的世界里任何东西都属于对象,即使类型也是对象的一员。 一般有常见的内建类型对象int,string,list等还有自己定义类型对象。针对这些类型,我们可以进行对象实例化。对象之间包含着很多复杂的关系。

python对象对应就是c在堆中分配的空间。而python的内建类型对象对应的空间是在静态初始化。对象一旦分配好了,空间就已经固定了,所以要想可变长,必须维护一个指向其他可变空间的地址空间的指针。

python object 对应c语言的表达

typedef struct _object {
    PyObject_HEAD
} PyObject;

#define PyObject_HEAD \
    _PyObject_HEAD_EXTRA\
    int obj_refcnt;
    struct _typeobject *obj_type;

obj_refcnt对应是引用计数,obj_type对应的是类型。
变长对象表达:

typedef struct {
    PyObject_HEAD
    long ob_lval;
}

#define PyObject_VAR_HEAD\
    PyObject_HEAD\
    int ob_size;

typedef struct {
    PyObject_VAR_HEAD
}  PyVarObject;

类型对象

在内存中分配空间,创建对象时,毫无疑问,我们需要指导对象占用的空间是多大,不同的对象占用的空间大小是不一样的。占用内存空间的大小这个元信息与对象的类型是紧密关系在一起,它会出现在对象类型之中。

typedef struct _typeobject {
    PyObject_VAR_HEAD
    char * tp_name;
    int tp_basicsize; 创建该类型分配的内存空间
    
    destructor tp_dealloc;
    printfunc tp_prinf;
    ...
    hashfunc tp_hash;
    ternaryfunc tp_call;
    ...
} PyTypeObject

对象的创建方式

python对象的创建有两种方式:

  1. 通过c api创建,如PyObject obj = PyObject_New(PyObject, &PyInt_Type)
  2. 另外一种是与对象相关的api,只能作用于某种类型的对象上,如PyObject *intobj = PyInt_Fromlong(10)

tp_base 表明继承关系,tp_new则是逐层查找非null定义并根据tp_basicsize生成对象内存空间。tp_init则为初始化阶段。

对象常用的函数簇

PyTypeObject 中有三个常用的函数簇,针对数字,列表,字典类型的函数集,分别是PyNumberMethods, PySequenceMethods, PyMappingMethods.

typedef PyObject* (*binaryfunc)(PyObject* , PyObject*);

typedef struct {
    binaryfunc nb_add;
    binaryfunc nb_substract;
    ....
} PyNumberMethods;

tp_as_number.nb_add定义了python对象+操作符的执行动作。

python的PyTypeObject的类型是什么

PyTypeObject PyType_Type = {
    PyObject_HEAD_INIT(&PyType_Type)
    0,
    "type",
    sizeof(PyHeapTypeObject),  /* tp_basicsize */
    sizeof(PyMemberDef),   /* tp_itemsize */
    ....
}

那么可以整理出这样的一个层次关系。
PyObject => PyTypeObject => PyType_Type(这个就是常说的metaclass) 对于不同内置类型的对象有着自己的PyType_Type.譬如int类型

PyTypeObject PyInt_Type = {
    PyObject_HEAD_INIT(&PyType_Type)
    0,
    "int",
    sizeof(PyIntObject),
    ....
}

a = ObjectB() 首先会生成一个PyTypeObject的ObjectB,然后a的ob_type指向该对象。

多态性的体现

对象的多态性来源于ob_type域,比如

void Print(PyObject* object){
    object->ob_type->tp_print(object);
}

垃圾回收

Py_Dealloc过程并不会真正去做释放内存的动作,而是采用内存对象池技术,通过这个技术可以避免内存频繁的申请和释放。

对象的分类

万物皆对象。