Python中的类和实例都是经过Python内的对象来实现的。Python中已经预先定义了一些类型对象。这些内建类型对象经过实例化,能够建立内建类型对象的实例对象。app
在Python中,对象就是为C中的结构体在堆上申请的一块内存,通常来讲,对象是不能被静态初始化的,而且也不能在栈空间上生存。惟一的例外就是类型对象,Python中全部的内建的类型对象都是被静态初始化的。函数
在Python中,一个对象一旦被建立,它在内存中的大小就是不变的了。这就意味着那些须要容纳可变长度数据的对象只能在对象内维护一个指向一块可变大小的内存区域的指针。ui
PyObject是整个Python对象机制的核心,定义以下:指针
// object.h typedef struct _object { _PyObject_HEAD_EXTRA Py_ssize_t ob_refcnt; struct _typeobject *ob_type; } PyObject;
其中_PyObject_HEAD_EXTRA定义以下:调试
// 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
能够看到release编译时不会定义Py_TRACE_REFS。code
PyObject类中ob_refcnt与内存引用计数相关,ob_type用来指定一个对象类型的类型对象。在Python中,对象机制的核心一个是引用计数,一个就是类型信息。对象
每个Python对象除了必须有这个PyObject内容外,还应该占有一些额外的内存,放置些其余的东西。好比float对象除了PyObject,还有一个额外的double变量,以下定义:内存
// object.h /* PyObject_HEAD defines the initial segment of every PyObject. */ #define PyObject_HEAD PyObject ob_base;
把浮点对象这样不包含可变长度数据的对象称为“定长对象”,而字符串对象这样包含可变长度数据的对象称为“变长对象”,它们的区别在于定长对象的不一样对象占用的内存大小是同样的,而变长对象的不一样对象占用的内存多是不同的。字符串
表示变长对象的结构体PyVarObject定义以下:get
// object.h typedef struct { PyObject ob_base; Py_ssize_t ob_size; /* Number of items in variable part */ } PyVarObject;
每个可变Python对象除了有PyVarObject内容外,还占有一些额外的内存,放置些其余的东西。好比list对象为变长对象,它的结构体以下:
// listobject.h typedef struct { PyObject_VAR_HEAD PyObject **ob_item; Py_ssize_t allocated; } PyListObject;
其中PyObject_VAR_HEAD定义了PyVarObject类型对象,以下:
// object.h /* PyObject_VAR_HEAD defines the initial segment of all variable-size container objects. */ #define PyObject_VAR_HEAD PyVarObject ob_base;
对象对应的类型对象定义以下:
// object.h typedef struct _typeobject { PyObject_VAR_HEAD const char *tp_name; Py_ssize_t tp_basicsize, tp_itemsize; /* Methods to implement standard operations */ destructor tp_dealloc; printfunc tp_print; // ... } PyTypeObject;
定义中包含了许多信息,主要分为4类:
在PyTypeObject中定义了大量的函数指针,这些函数指针最终都会指向某个函数,或者指向NULL,能够视为类型对象中所定义的操做。在这些操做信息中,有三组很是重要的操做族:tp_as_number,tp_as_sequence和tp_as_mapping,分别指向PyNumberMethods,PySequenceMethods和PyMappingMethods函数族。PyNumberMethods、PySequenceMethods、PyMappingMethods分别定义了做为一个数值对象、序列对象和关联对象应该支持的操做。
类型对象的类型是PyType_Type:
PyTypeObject PyType_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "type", /* tp_name */ sizeof(PyHeapTypeObject), /* tp_basicsize */ sizeof(PyMemberDef), /* tp_itemsize */ (destructor)type_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc)type_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ (ternaryfunc)type_call, /* tp_call */ 0, /* tp_str */ (getattrofunc)type_getattro, /* tp_getattro */ (setattrofunc)type_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS, /* tp_flags */ type_doc, /* tp_doc */ (traverseproc)type_traverse, /* tp_traverse */ (inquiry)type_clear, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyTypeObject, tp_weaklist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ type_methods, /* tp_methods */ type_members, /* tp_members */ type_getsets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ type_init, /* tp_init */ 0, /* tp_alloc */ type_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ (inquiry)type_is_gc, /* tp_is_gc */ };
Python的C API分为两类,一类称为范性的API(AOL,Abstract Object Layer),这类API都具备诸如PyObject_*的形式,能够应用在任何Python对象上;另外一类是与类型相关的API(COL,Concrete Object Layer),这类API一般只能做用在某一种类型的对象上,对于每一种内建对象,Python都提供了这样的一组API。
本文做者:whj0709
阅读原文本文为云栖社区原创内容,未经容许不得转载。