二、对象体系
pythoner有句话常说:“一切皆对象”,说是这么说,但是理解吗?
首先,我们来看看对象的定义:就是数据和基于这些数据的操作的集合。
python是用C编写,C里面可没有对象的概念,那这个究竟是什么呢?
在python中,对象实际是为C的结构体在堆上申请的一片内存。这里的堆是Heap的概念。
让我们还是从object.h这个头文件一窥究竟吧
在文件开头,有一长串注释,在里面有下面几个要点:
1.Objects are structures allocated on the heap.这就是上面所说的,对象实际是为C的结构体在堆上申请的一片内存。
2.内存管理的核心:An object has a 'reference count' that is increased or decreased when a
pointer to the object is copied or deleted; 这也是GIL锁的原因之一。
3.对象一旦分配,便不可更改。Objects do not float around in memory; once allocated an object keeps
the same size and address.这是为python的内存管理服务的。
4.所有对象都有一个核心东西PyObject。Objects are always accessed through pointers of the type 'PyObject *'.
5.A standard interface exists for objects that contain an array of items
whose size is determined when the object is allocated.
注释里提到了PyObject,那这是啥东西呢?
typedef struct _object {
PyObject_HEAD
} PyObject;
#define PyObject_HEAD \
_PyObject_HEAD_EXTRA \
Py_ssize_t ob_refcnt; \
struct _typeobject *ob_type;
/*垃圾回收里的标记清除会用到*/
#define _PyObject_HEAD_EXTRA \
struct _object *_ob_next; \
struct _object *_ob_prev;
Py_ssize_t是python的一个有趣的类型,是为了解决CPU位数问题的一个整形
在pyport.h可以看见定义
typedef ssize_t Py_ssize_t;
python里面还有一种定义,是包含着个数信息的那种对象:
typedef struct {
PyObject_VAR_HEAD
} PyVarObject;
*/
#define PyObject_VAR_HEAD \
PyObject_HEAD \
Py_ssize_t ob_size; /* Number of items in variable part */
如注释所述,还包含items的个数信息
占用内存空间的信息在哪呢?隐含在_typeobject这个里面
typedef struct _typeobject {
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;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
cmpfunc tp_compare;
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) */
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 */
long tp_flags;
const char *tp_doc; /* Documentation string */
/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* Assigned meaning in release 2.1 */
/* rich comparisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;
/* Added in release 2.2 */
/* 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;
#ifdef COUNT_ALLOCS
/* these must be last and never explicitly initialized */
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;
从上面可以看出:
*tp_name 类型名
tp_basicsize, tp_itemsize内存分配的大小
一些标准操作,例如print
类型信息
那么对象是如何创建的呢?
1.C API,也就是python的C扩展包 2.内建对象的API
从上述的结构体当中,可以看到这么一段话:
/* Method suites for standard classes */
PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
这实际上指的是每一种对象都有着三种操作,数值,序列,关联
这也是为啥一个字符串你可以进行如下操作:
a = '234'
for i in a:
print(i)
2
3
4
python的类型也是一个对象,每一个对象都对应着一个类型,比如
a = 1
a对应着的是int类型
那类型的类型是啥呢?我们进入到typeobject.h中看看
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_compare */
(reprfunc)type_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)_Py_HashPointer, /* 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 */
type_richcompare, /* 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 */
};
这就是传说中的metaclass,下述就可以看出了
"type", /* tp_name */
在python中输入如下:
type(type)
Out[9]: type
好了现在我们可以梳理一下大致的python的对象类型:(采用的《python源码剖析》里的,我觉得这里的分类很好)
Fundamental对象:类型对象
Numeric对象:long, float, boolean
Sequence对象:list, tuple, string
Mapping对象:dict
Internal对象:虚拟机运行时对象function, code, frame, module, method
注:很可怜的,python的基础类型确实只有这么少。