Python源码剖析学习二
Python对象初探
在Python中,一切都是对象。连类型也是一种对象。
在Python中,对象就是为C中的结构体在堆上申请的一块内存。一般来说,对象是不能被静态初始化的,并且也不能在栈空间上生存。
唯一的例外就是类型对象,Python中所有的内建的类型对象(如整数类型对象,字符串类型对象)都是被静态初始化的。
在Python中,一个对象一旦被创建,它在内存中的大小就是不变的了。这就意味着那些需要容纳可变长度数据的对象只能在对象内维护一个指向一块可变大小的内存区域的指针
PyObject是整个Python对象机制的核心。
typedef struct _object{
PyObject_HEAD
}PyObject;
注意PyObject_HEAD,Python对象的秘密都隐藏在这里。
#define PyObject_HEAD
_PyObject_HEAD_EXTRA
int ob_refcnt;
struct _typeobject *ob_type;
在PyObject的定义中,ob_refcnt与Python的内存管理机制有关,它实现了基于引用计数的垃圾收集机制。
ob_type是一个指向_typeobject结构体的指针,这个结构体对应着Python内部的一种特殊对象,它是用来指定一个对象类型的类型对象。
在Python中,对象机制的核心其实非常简单,一个是引用计数,一个就是类型信息。
例如一个Python的整数对象
typedef struct {
PyObject_HEAD //Python对象都具有的
long ob_ival; //整数对象特有的信息
} PyIntObject;
Python在PyObject对象之外,还有一个表示这类对象的结构体——PyVarObject
#define PyObject_VAR_HEAD \
PyObject_HEAD
int ob_size;
typedef struct {
PyObject_VAR_HEAD
} PyVarObject;
整数对象不包含可变长度数据的对象称为"定长对象",而字符串对象这样包含可变长度数据的对象称为"变长对象"。
在Python内部,每一个对象都拥有相同的对象头。在Python中,对对象的引用非常的统一,我们只需要用一个PyObject*指针就可以引用任意的一个对象。
Python内部如何从无到有地创建出一个整数对象,Python会有两种方法。第一种是通过Python C API来创建,第二种是通过类型对象PyInt_Type.
Python的C API分成两类:
一类称为范型的API,或者称为AOL(Abstract Object Layer)。这类API都具有诸如PyObject_***的形式,可以应用在任何Python对象身上,比如输出对象的PyObject_Print
另一类是与类型相关的API,或者称为COL(Concrete Object Layer)。这类API通常只能作用在某一种类型的对象上,对于每一种内建对象,Python都提供了这样的一组API。
在Python2.2之后,int是一个继承自object的类型,类似于int对应着Python内部的PyInt_Type,object在Python内部则对应着PyBaseObject_Type