虽然自己会吐槽python这语言让人受不了的慢,不过也不得不说python语言在语法上的精炼,在写代码的时候确实会比java方便一些。。。不过由于python无法像java一样项目的开始先定义一套强类型限制的接口,所以总感觉在写python的时候有点不踏实。。。不过pycharm从某种程度上通过注释也能减轻一点这方面的担忧。。
好了。。。。。决定了要看一下python的实现。。。这里就先从python的对象结构来说吧。。。。
在python中,所有的东西都是对象,整数是,方法也是,。。总之什么都是。。。。
在看python的代码实现中,可以随处看到指针类型:PyObject*,那么我们就先来看看PyObject这到底是怎么定义的吧:
typedef struct _object { //这个是所有python对象的基础,这个是不可变对象 PyObject_HEAD } PyObject;
他就是整个python环境中最上层的对象结构,很简单,就包括一个对象头部,那么来看看它的定义:
//通过这个结构,将所有对象构成一个双链表 /* 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 //所有对象共有的数据,这个放在所有对象内存的最开始部分,首先是构成对象链表的前后执指针,其次是引用数量,以及它的类型对象 /** (1)前后指针,构成循环链表 (2)引用计数 (3)类型对象 **/ /* PyObject_HEAD defines the initial segment of every PyObject. */ #define PyObject_HEAD _PyObject_HEAD_EXTRA Py_ssize_t ob_refcnt; struct _typeobject *ob_type;
可以看出,头部由3部分来构成,首先是一个前后指针,用于将对象构成一个双向的链表,其次就是比较重要的引用计数了。。。然后还有就是类型对象----》每一个对象都有一个指针指向其所指向的类型对象。。。
既然看到了引用计数,那么就来说说python的GC吧。。。它跟java在GC最大的不同点就是有一套基于引用计数的内存回收。。。
(1)每一个对象都关联一个引用计数,当这个计数为0的时候,那么它的内存就可以被回收了
(2)对于有循环引用的情况,python也有一套可达性分析的gc来回收内存。。当然它这部分就比java简单的多了
上面看的时最基础的PyObject结构。。。另外这里还有另外一种结构:PyVarObject,它用于指代一些变长对象,主要是一些容器。。。。
//一般都是一些容器啥的 typedef struct { //可变对象的基础 PyObject_VAR_HEAD } PyVarObject; //即使是可变对象,首先也是有一个统一的对象头部,ob_size一般用于记录容器中数据项个数,注意这里不是字节数 #define PyObject_VAR_HEAD PyObject_HEAD Py_ssize_t ob_size; /* Number of items in variable part */ #define Py_INVALID_SIZE (Py_ssize_t)-1
它其实也就是扩展了一个0b_size字段。。。本质上也是与PyObject统一的。。。。所以对于PyVarObject,也可以用PyObject指针来引用。。从而达到了统一。。。。
通过上面的内容,我们知道,所有的对象,都会有一个ob_type指针域,用于指向当前对象的类型对象,那么接下来来看看类型对象的定义:
//这个用来指定一个对象的类型对象 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; //在调用print打印类型的时候,将会调用这里来进行输出 getattrfunc tp_getattr; //getter函数 setattrfunc tp_setattr; //setter函数 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; //获取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; //将当前对象作为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;
可以看到,这里主要是定义了很多公共的函数。。。。同时这里可以看到最开始他也定义了一个变长对象的头部PyObject_VAR_HEAD
那么也就是说,类型对象本身也是一个对象,也可以用PyObject指针来引用。。。。
嗯。。那么。。这里问题就来了。。。。既然类型对象也是一个对象。。。。那么类型对象他自己的类型对象是啥呢。。。?
嗯。。。在python中定义了一个最顶层的类型对象。。。。。
//最顶层的类型对象,它进行一个类型对象的自引用 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 */ };
这里可以看到它的类型对象本身引用了自己。。。。。
以后可以看到,所有的python类型对象都将它自己的类型对象指向了PyType_Type
好了。。基本上比较粗略的了解了python的对象结构。。。。。