本来想写python type object之间的区别,联系,可是看着写着,发现东西太多,因而分几个部分来写吧,这是第一部分,python中的万物理论,对象python
python中一切皆对象,不管是一个数字或一个字符串或一个类或一个类实例等都是对象,那么对象究竟是什么,来看object.h源码文件中对于对象的描述:git
在Python中,对象就是为C中的结构体在堆上申请的一块内存。通常来讲,对象是不能被静态初始化的,而且也不能在栈空间上生存。惟一的例外是类型对象,Python中全部的内建类型对象都是被静态初始化的。github
在Python中,一个对象一旦被建立,它在内存中的大小就是不变的了。这就意味着那些须要容纳可变长度数据的对象只能在对象内维护一个指向一块可变大小的内存区域的指针。python2.7
一个对象维护着一个“引用计数”,其在一个指向这个对象的指针复制或删除时增长或减小。当这个引用计数变为零时,也就是说已经没有任何指向这个对象的引用,这个对象就能够从堆上被移除。spa
一个对象有着一个类型(type),来肯定它表明和包含什么类型的数据。一个对象的类型在它被建立时是固定的。类型自己也是对象。一个对象包含一个指向与之相配的类型的指针。类型本身也有一个类型指针指向着一个表示类型对象的类型的对象“type”,这个type对象也包括一个类型指针,不过是指向它本身的。指针
基本上Python对象的特性就是这些,那么,在C的层面上,一个Python对象的这些特性是如何实现的呢?code
python中一切皆对象,全部对象都基于PyObject,都有共同的内容定义,这些内容在object.h中大约106行定义。对象
typedef struct _object { _PyObject_HEAD_EXTRA Py_ssize_t ob_refcnt; struct _typeobject *ob_type; } PyObject;
阅读以上代码,咱们会发现:内存
在Python2中,一个int类型的对象的值在C中的类型是不变的(int),因此它在内存中占据的大小也是不变的。可是一个字符串对象事先咱们根本不可能知道它所维护的值的大小。在C中,根本就没有“一个字符串”的概念,字符串对象应该维护“n个char型变量”。不仅是字符串,list等对象也应该维护“n个PyObject对象”。这种“n个……”也是一类Python对象的共同特征,所以,Python在PyObject以外,还有一个表示这类对象的结构体-PyVarObject,在object.h中大约112行定义。:字符串
typedef struct { PyObject ob_base; Py_ssize_t ob_size; /* Number of items in variable part */ } PyVarObject;
咱们把相似Python2中的int对象这样不包含可变长度的对象称为“定长对象”,而字符串对象这样包含可变长度数据的对象称为“变长对象”。
为何要强调Python2中的int对象呢?由于在Python3中,int类型的底层实现直接使用了Python2中的long类型的底层实现,也就是说,如今的int是之前的long类型,而之前的int类型已经不复存在。而long类型实际是一个变长对象。
变长对象一般都是容器,ob_size这个成员实际上就是指明了变长对象中一共容纳了多少个元素,即前面讲的“n个......”。
从PyVarObject的定义能够看出,变长对象实际就是在PyObject对象后面加了个ob_size,所以,对于任意一个PyVarObject,其所占用的内存开始部分的字节就是一个PyObject。在Python内部,每个对象都拥有着相同的对象头部。这就使得在Python中,对对象的引用变得很是的统一,咱们只须要用一个PyObject *指针就能够引用任意的一个对象。