0x01 PyObject
/* 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;
/* PyObject_HEAD defines the initial segment of every PyObject. */
#define PyObject_HEAD \
_PyObject_HEAD_EXTRA \
Py_ssize_t ob_refcnt; \
struct _typeobject *ob_type;
#define PyObject_VAR_HEAD \
PyObject_HEAD \
Py_ssize_t ob_size; /* Number of items in variable part */
typedef struct _object {
PyObject_HEAD
} PyObject;
typedef struct {
PyObject_VAR_HEAD
} PyVarObject;
/* 预处理完后的结构体格式 */
typedef struct _object {
struct _object *_ob_next;
struct _object *_ob_prev;
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
typedef struct {
struct _object *_ob_next;
struct _object *_ob_prev;
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
Py_ssize_t ob_size;
} PyVarObject;
python
的所有对象都是在堆(heap
)上创建的。
为了确保对象可以被正确的垃圾回收(garbage-collected
),在对象的使用上我们会应用一些特定的规则:①对象不应该在静态区或者栈上创建;②对象只能通过特定的宏和函数来访问。
第一条规则对类型对象(type objects
)是例外的,python
内建的标准类型对象(int
、list
等)是在静态区初始化的,但是在python 2.2
版本为了使type/class
统一,标准类型也可能在堆上创建(although work on type/class unification for Python 2.2 made it possible to have heap-allocated type objects too
)
引用计数(reference count
):每一个对象都有一个引用计数器属性,当一个指针指向或者删除与这个对象的关联时(when a pointer to the object is copied or deleted
),引用计数会相应的增加或减少。当引用计数减为0
时,即这个对象没有任何引用了,它会在堆(heap
)上释放内存。
类型(type
):每一个对象都有一个类型属性,这个类型确定了这个对象表示的是什么、它包含了哪种类型的数据(what it represents and what kind of data it contains
)。每个对象创建的时候它的类型就固定了。类型也是一种对象(Types themselves are represented as objects
);对象通过指针指向相应的类型对象,类型对象它自己也有一个类型对象的指针指向type
对象,type
对象也有一个类型对象指针,但是它是指向它自己的。
对象不会在内存中变化(float
),一旦给对象分配了内存,它会保持相同的大小和地址。但是如果对象想保存变长的(variable-size
)数据,它可以包含一个指针,指向一个变长的对象。不是所有相同类型的对象都有相同的大小,但是对象大小在分配完内存以后是不允许改变的。(有了这些限制以后,对象的引用才可以用一个简单的指针来表示。移动(moving
)一个对象,需要更新它的全部指针;改变(changing
)一个对象时,如果它的旁边有另一个对象,则需要移动它)。
在python
中,所有对象都是通过PyObject *
指针来访问的。PyObject
是一个最近本的结构体,它里面只包含了引用计数和类型。一个对象实际分配的内存肯定包含了其他数据,这些数据在创建(casting
)了指向更长结构体类型的指针后才能被访问(that can only be accessed after casting the pointer to a pointer to a longer structure type
)。这个更长的结构体也必须包含引用计数和类型属性,这块可以使用PyObject_HEAD
宏(每个对象都包含PyObject_HEAD
宏,宏的作用是更利于以后的变化(to accommodate for future changes
))。The implementation of a particular object type can cast the object pointer to the proper type and back
。
欢迎关注微信公众号(coder0x00)或扫描下方二维码关注,我们将持续搜寻程序员必备基础技能包提供给大家。
网友评论