1. PyObject PyObject定义在object.h
typedef struct _object { PyObject_HEAD } PyObject;
PyObject_HEAD定义在object.h中
#define PyObject_HEAD \ Py_ssize_t ob_refcnt; \ struct _typeobject *ob_type;
ob_refcnt为引用计数器, 若某个PyObject*
指向该对象, 则ob_refcnt + 1
; 若某个PyObject*
被删除, 则ob_refcnt - 1
; 若ob_refcnt == 0
, 则将该对象从堆中删除.
_typeobject
为结构体, 内部装有该对象类型的信息, ob_type为结构体指针
PyObject仅仅是Python各个对象的父类.
typedef struct { PyObject_HEAD long ob_ival, } PyIntObject;
PyIntObject不仅具有PyObject的所有参数, 还多了一个long类型的数值, 数值就存储于此
2. 不定长变量 如果是int类型的变量, 很容易通过ob_ival
存储数据, 但如果需要保存string类型变量, 则Python无法知道用户输入的string会有多少char类型变量, 这时就需要不定长变量的对象
#define PyObject_VAR_HEAD \ PyObject_HEAD \ Py_ssize_t ob_size; typedef struct { PyObject_VAR_HEAD } PyVarObject;
ob_size
表示该对象所具有的元素个数, 所以PyVarObject
可以表示变长对象. 假设list有5个元素, 则ob_size为5.
3. 类型对象 _typeobject
结构体如下:
typedef struct _typeobject { PyObject_VAR_HEAD const char *tp_name; Py_ssize_t tp_basicsize, tp_itemsize; destructor tp_dealloc; printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; cmpfunc tp_compare; reprfunc tp_repr; PyNumberMethods *tp_as_number; PySequenceMethods *tp_as_sequence; PyMappingMethods *tp_as_mapping; hashfunc tp_hash; ternaryfunc tp_call; reprfunc tp_str; getattrofunc tp_getattro; setattrofunc tp_setattro; PyBufferProcs *tp_as_buffer; long tp_flags; const char *tp_doc; traverseproc tp_traverse; inquiry tp_clear; richcmpfunc tp_richcompare; Py_ssize_t tp_weaklistoffset; getiterfunc tp_iter; iternextfunc tp_iternext; 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; inquiry tp_is_gc; PyObject *tp_bases; PyObject *tp_mro; PyObject *tp_cache; PyObject *tp_subclasses; PyObject *tp_weaklist; destructor tp_del; #ifdef COUNT_ALLOCS Py_ssize_t tp_allocs; Py_ssize_t tp_frees; Py_ssize_t tp_maxalloc; struct _typeobject *tp_prev ; struct _typeobject *tp_next ; #endif } PyTypeObject;
4. 对象的创建 Python有两种方式创建一个整数对象
通过AOL(Abstract Object Layer)创建PyObject* intObj = PyObject_New(PyObject, &PyInt_Type);
通过COL(Concrete Object Layer)创建 这种API只能作用于某一类型的对象, 对于int对象, 可以使用一下表达式:PyObject* intObj = PyInt_FromLong(10 );
下面是a=int(10)的实现流程:
调用PyInt_Type
中的tp_new
如果PyInt_Type
中的tp_new为null, 则通过tp_base
指定的基类调用基类的tp_new
通过tp_new
为对象申请内存, 并转向PyInt_Type
的tp_init
通过tp_init
完成初始化对象
5. 对象的行为 PyTypeObject
中有很多函数指针, 这些函数指针指向某个函数或是null. 例如:
tp_hash
指明该类型对象所能生成的hash值
tp_as_number
指向PyNumberMethods
, 定义了一个数值对象支持的操作
tp_as_sequence
指向PySequenceMethods
, 定义了一个list对象支持的操作
tp_as_mapping
指向PyMappingMethods
, 定义了一个dict对象支持的操作
6. 类型的类型 Python的类型其实是一个对象, 那么这个类型对象的类型就是PyType_Type
:
PyTypeObject PyType_Type = { PyObject_HEAD_INIT(&PyType_Type) 0 , "type" , sizeof (PyHeapTypeObject), sizeof (PyMemberDef), (destructor)type_dealloc, 0 , 0 , 0 , type_compare, (reprfunc)type_repr, 0 , 0 , 0 , (hashfunc)_Py_HashPointer, (ternaryfunc)type_call, 0 , (getattrofunc)type_getattro, (setattrofunc)type_setattro, 0 , Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, type_doc, (traverseproc)type_traverse, (inquiry)type_clear, 0 , offsetof(PyTypeObject, tp_weaklist), 0 , 0 , type_methods, type_members, type_getsets, 0 , 0 , 0 , 0 , offsetof(PyTypeObject, tp_dict), 0 , 0 , type_new, PyObject_GC_Del, (inquiry)type_is_gc, };
所有PyTypeObject
对象都是通过PyType_Type
创建, 以下是PyType_Object
和PyType_Type
的关系:
>>> int .__class__<type 'type' > >>> type .__class__<type 'type' >
上述代码中的'type'指的就是PyType_Type
, 也就是Python中的metaclass. 以下是PyInt_Type
和PyType_Type
之间的关系:
PyTypeObject PyInt_Type = { PyObject_HEAD_INIT(&PyType_Type) 0 , "int" , sizeof (PyIntObject), 0 , (destructor)int_dealloc, (printfunc)int_print, 0 , 0 , (cmpfunc)int_compare, (reprfunc)int_repr, &int_as_number, 0 , 0 , (hashfunc)int_hash, 0 , (reprfunc)int_repr, PyObject_GenericGetAttr, 0 , 0 , Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE, int_doc, 0 , 0 , 0 , 0 , 0 , 0 , int_methods, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , int_new, (freefunc)int_free, };
以下是宏定义PyObject_HEAD_INIT
:
#ifdef Py_TRACE_REFS #define _PyObject_EXTRA_INIT 0, 0, #else #define _PyObject_EXTRA_INIT #endif #define PyObject_HEAD_INIT(type) \ _PyObject_EXTRA_INIT \ 1, type,
7. Python对象的多态性 虽然Python有很多类型对象, 但是函数之间传递使用的都是PyObject*
. Python可以通过对象的ob_type来判定该对象的具体操作, 例如:
long PyObject_Hash (PyObject* v) { PyTypeObject* tp = v->ob_type; if (tp->tp_hash!=null) return (*tp->tp_hash)(v); ...... }
8. 引用计数 Python通过ob_refcnt
来实现垃圾回收机制, 通过Py_INCREF(op)
和Py_DECREF(op)
两个宏来增加和减少一个对象的引用计数. 当一个对象的引用计数减少到0后, Py_DECREF
将调用该对象的析构函数来释放内存和资源.ob_refcnt
是一个32位的整数变量, 所以一个对象的引用个数是有限的. 另外, 类型对象不受引用计数影响, 即永远不会被析构. 以下是有关引用计数的宏:
#define _Py_NewReference(op) ((op)->ob_refcnt = 1) #define _Py_Dealloc(op) ((*(op)->ob_type->tp_dealloc)((PyObject*)(op)) #define Py_INCREF(op) ((op)->ob_refcnt++) #define Py_DECREF(op) \ if (--op->ob_refcnt != 0) \ ; \ else \ _Py_Dealloc((PyObject*)(op))
9. Python对象的分类 Python的对象从概念上分为5类:
Fundamental对象: 类型对象(type)
Numeric对象: 数值对象(int, float, bool)
Sequence对象: 容纳其他对象的序列集合对象(string, list, tuple)
Mapping对象: 类似于C++中的map的关联对象(dict)
Internal对象: Python虚拟机在运行时内部使用的对象(function, code, frame, module, method)