[绝对原创 转载请注明出处]
Python源码剖析
——对象机制
本文作者: Robert Chen([email protected])
1. 对象
在Python的世界中,一切都是对象,一个整数是一个对象,一个字符串也是一个对象,更为奇妙的是,类型也是一个对象,整数类型是一个对象,字符串类型也是一个对象。从1980年Guido在那个圣诞节揭开Python世界的大幕开始,一直到现在,Python经历了一次一次的升级,但是其实现语言一直都是ANSI C。我们知道,C并不是一个面向对象的语言,那么在Python中,它的对象机制是如何实现的呢?
对于人的思维来说,对象是一个比较形象的概念,而对于计算机来说,对象实际上是一个抽象的概念。计算机并不能理解这是一个整数,那是一个字符串,对于计算机来说,它所知道的一切都是字节。通常的说法是,对象是数据以及基于这些数据的操作的集合。在计算机上,一个对象实际上就是一片被分配的内存空间,这些内存可能是连续的,也有可能是离散的,这都不重要,重要的是这片内存在更高的层次上可以作为一个整体来考虑,这个整体就是一个对象。在这片内存中,存储着一系列的数据以及可以对这些数据进行修改或读取的一系列操作的代码。
在Python中,对象就是在堆上申请的结构体,对象不能是被静态初始化的,并且也不能是在栈空间上生存的。唯一的例外就是类型对象(type object),Python中所有的类型对象都是被静态初始化的。
在Python中,一个对象一旦被创建,它在内存中的大小就是不变的了。这就意味着那些需要容纳可变长度数据的对象只能在对象内维护一个指向一个可变大小的内存区域的指针。为什么要设定这样一条特殊的规则呢,因为遵循这样的规则可以使通过指针维护对象的工作变得非常的简单。因为一旦允许对象的大小可在运行期改变,我们可以考虑如下的情形。在内存中有对象A,并且其后紧跟着对象B。如果运行期某个时刻,A的大小增大了,这意味着必须将整个A移动到内存中的其他位置,否则A增大的部分将覆盖原本属于B的数据。一旦将A移动到内存中的其他位置,那么所有指向A的指针必须立即得到更新,光是想一想,就知道这样的工作是多么的恐怖。
在Python中,所有的东西都是对象,而所有的对象都拥有一些相同的内容,这些内容在PyObject中定义,PyObject是整个Python对象机制的核心。
[object.h]
typedef struct _object {
PyObject_HEAD
} PyObject;
实际上,PyObject是Python中不包含可变长度数据的对象的基石,而对于包含可变长度数据的对象,它的基石是PyVarObject:
[object.h]
typedef struct {
PyObject_VAR_HEAD
} PyVarObject;
这两个结构体构成了Python对象机制的核心基石,从代码中我们可以看到,Python的对象的秘密都隐藏在PyObject_HEAD与PyObject_VAR_HEAD中。
[object.h]
#ifdef Py_TRACE_REFS
/* 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;
#define _PyObject_EXTRA_INIT 0, 0,
#else
#define _PyObject_HEAD_EXTRA
#define _PyObject_EXTRA_INIT
#endif
/* PyObject_HEAD defines the initial segment of every PyObject. */
#define PyObject_HEAD /
_PyObject_HEAD_EXTRA /
int ob_refcnt; /
struct _typeobject *ob_type;