python-源码阅读(2)-pyObject

pyObject

1
2
3
4
5
6
7
8
9
10
11
12
13
[object.h]
typedef struct _object {
# Py_DEBUG implies Py_TRACE_REFS
# Py_TRACE_REFS 则对象结构会变成是一个双向列表, 所有堆中活动的对象都在这列表中,Py_TRACE_REFS 则对象结构会变成是一个双向列表,所有堆中活动的对象都在这列表中,与debug相关
_PyObject_HEAD_EXTRA

# typedef int Py_ssize_t;
# ob_refcnt 为int类型的应用计数
Py_ssize_t ob_refcnt;

# type 结构体
struct _typeobject *ob_type;
} PyObject;

type

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
[typestruct.h]
typedef struct _typeobject {

# 扩展 ob_size 为对象提供长度的概念
PyObject_VAR_HEAD

# 开发引用的
const char *tp_name; /* For printing, in format "<module>.<name>" */

# 计算该类型实例的字节大小
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

/* Methods to implement standard operations */

# 指向实例析构函数的指针
destructor tp_dealloc;

# 保留插槽,以前用于Python 2.x中的打印格式。
printfunc tp_print;

# 指向get-attribute-string函数的可选指针。
getattrfunc tp_getattr;

# 指向get-attribute-string函数的可选指针。
setattrfunc tp_setattr;

# 指向另一个结构的指针
PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
or tp_reserved (Python 3) */
# 指向实现内置函数的函数的可选指针 repr()。
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) */

# 指向实现内置函数的函数的可选指针 hash()。
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 */

/* call function for all accessible objects */
traverseproc tp_traverse;

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

/* 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;

} PyTypeObject;
这些字段中还包括其他python协议的字段,如下所示。

1.数字协议 - 实现此协议的类型将具有PyNumberMethods *tp_as_number 字段的实现。此字段是对一组实现数字操作的函数的引用,这意味着该类型将支持具有包含在tp_as_number 集合中的实现的算法。例如,非数字set类型在此字段中有一个条目,因为它支持算术运算,例如-,<=等等。
2.序列协议 - 实现此协议的类型将在PySequenceMethods *tp_as_sequence 字段中具有值。这意味着该类型将支持部分或全部的的序列的操作 ,例如len,in等
3.映射协议 - 实现此协议的类型将具有一个值PyMappingMethods *tp_as_mapping。这将使这种类型的实例像python词典一样使用字典下标语法来设置和访问键值映射。
4.迭代器协议 - 实现此协议的类型将在getiterfunc tp_iter 可能的iternextfunc tp_iternext字段中具有值,并且可以使用类型的实例,如python迭代器。
5.缓冲协议 - 实现此协议的类型将在该PyBufferProcs *tp_as_buffer 字段中具有值。这些函数将允许访问类型的实例作为输入/输出缓冲区。

垃圾回收机制

源码中, 通过 Py_INCREF(op) 和 Py_DECREF(op) 两个宏来增加和较少引用计数的.

1
2
3
4
5
6
7
8
9
10
11
12
13
[object.h]

#define Py_INCREF(op) ( \
((PyObject *)(op))->ob_refcnt++)

#define Py_DECREF(op) \
do { \
PyObject *_py_decref_tmp = (PyObject *)(op); \
if (--(_py_decref_tmp)->ob_refcnt != 0) \
_Py_CHECK_REFCNT(_py_decref_tmp) \
else \
_Py_Dealloc(_py_decref_tmp); \
} while (0)

当一个对象的引用计数减少到0后,Py_DECREF(op)会调用该对象”析构函数”进行释放.

1
2
#define _Py_Dealloc(op) (                               \
(*Py_TYPE(op)->tp_dealloc)((PyObject *)(op)))