[python]源码-对象的创建和行为

  (明天论文就要送审了!!!距离毕业一个月!!!)

  现在还记得刚开始学python时候被这种动态语言惊到的那种感觉,列表和字典对象可以随意伸缩,简直不能更帅了,但是一直不知道内部到底是怎么实现的,python源码用C实现的,但是C是过程性语言啊。

  说怎么实现之前,先捋捋什么是对象,对这个我觉得《python源码剖析》这本书里面的解释很有意思:“一个对象实际上就是一片被分配的内存空间,这些内存可能是连续的,也可能是不连续的,这都不重要,重要的是这片内存在更高的层次上可以作为一个整体来考虑,这个整体就是对象,在这片内存中,存储着一系列的数据以及可以对这些数据进行修改和读取操作的代码”,一个很有意思的角度。

  一个对象被创建后,它所占用的内存大小就是不可变的了,这意味着对可变长度的数据来说(比如字符串),只能在对象内部维护一个指向可变大小内存区域的指针。

  在python中,一切皆是对象,其中所有对象的核心就是一个叫PyObject的结构体

1 typedef struct _object{
2     int ob_refcnt;
3     struct _typeobject *ob_type;
4 }PyObject;

  其中,ob_refcnt为引用计数,_typeobject决定了对象的类型,ob_type指向了一个类型对象(我的理解:基类),这个结构体将出现在所有对象所占有内存的最开始的地方,就比如在一个int类中:

1 typedef struct{
2 PyObject _HEAD;
3 long ob_ival;
4 }PyIntObject;

int值得信息就保存在ob_ival中,这是python2.5中的int对象,如果是list这种可变长度的对象,这种方法显然是不行的,那么就把头部结构体PyObject中加一个表示此对象占有多少个对象的信息ob_size,这个值也就表明了边长对象中一共有多少个元素:

1 #define PyObject_VAR_HEAD
2     PyObject_HEAD
3     int ob_size;
4
5 typedef struct{
6 PyObject_VAR_HEAD
7 }PyVarObject;

所以,python中对象的内存表示是下面这个样子的:

从上面可以看到,对象的类型完全由ob_type指向的类型对象决定的,那么类型对象是什么鬼?

typedef struct _typedefobject{
PyObject_VAR_HEAD
char*tp_name;
int tp_basicsize,tp_itemsize;
destructor tp_dealloc;
printfunc tp_print;
hashfunc tp_hash;
ternaryfunc tp_call;
/*……*/
}PyTypeObject;

*tp_basicsize,tp_itemsize指定了分配内存空间的大小

*其余的带有func字眼的指向函数的指针表明了这个对象携带的操作

那么,对象是怎么创建的?

首先要说明在python新式类中,所有的对象的基类都是object,就像java中所有对象的基类都是Object所构成的单根类体系一样,也就是说,所有的对象都会自动继承其基类的所有方法。

在需要创建一个对象的时候,比如创建int对象需要用到的PyInt_Type对象时候,先寻找PyInt_Type类中的tp_new指针,如果这个指针为null,就寻找其父类,比如object中的tp_new指针,用这个指针指向的函数来创建对象,它指向的函数会首先查看PyInt_Type中的tp_basicsize字段,根据这个字段的信息来决定为这个对象分配多少内存,当创建完成后,会在PyInt_Type中寻找tp_init,用其指向的函数来初始化tp_new分配的内存。我理解的是,tp_new就相当于python类中的__new__静态类方法,tp_init就相当于__init__方法。

可以看到,在PyTypeObject中有很多只想函数的指针,这些函数指针也就决定了对象的行为,其中有三个非常重要的函数指针指向三个操作族:

tp_as_number-------->PyNumberMethods

tp_as_sequence------>PySequenceMethods  (列表list)

tp_as_mapping------>PyMappingMethods    (字典dict)

对每一种对象来说,可以同时指向三种操作族,可以通过哪些钩子方法实现,比如__getitem__,__setitem__

参考资料:python源码剖析

时间: 2024-10-25 11:07:40

[python]源码-对象的创建和行为的相关文章

[python 源码]整数对象的创建和维护

刚开始学python时候,发现一个很迷惑的现象,一直到看了源码后才知道了: >>> a=6 >>> b=6 >>> a is b True 想用同样的参数初始化两个对象,结果却是,这两个对象其实是同样的对象????逗我呢? >>> a=666 >>> b=666 >>> a is b False 这又是怎么回事?为什么现在又是False了??? 这些不同,主要来自于python中对待小整数和大整数的

《python源码剖析》笔记 python中的List对象

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.PyListObject对象 --> 变长可变对象,可看作vector<PyObject *> typedef struct{ PyObject_VAR_HEAD //其中的ob_size表示实际被使用的内存的数量 PyObject **ob_item;//ob_item为指向元素列表的指针,实际上,Python中的list[0]就是ob_item[0] int allocat

《python源码剖析》笔记 python中的Dict对象

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.PyDictObject对象 -->  C++ STL中的map是基于RB-tree的,搜索时间复杂度是O(logN) PyDictObject采用了hash表,时间复杂度是O(1) typedef struct{ Py_ssize_t me_hash; //me_key的hash值,避免每次查询都要重新计算一遍hash值 PyObject *me_key; PyObject *me_

《python源码剖析》笔记 python对象初探

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.      在python中,对象就是为C中的结构体在堆上申请的一块内存.对象不能被静态初始化,也不能在栈空间生存.但内建的类型对象都是被静态初始化的. 2.      对象创建后大小不变.可变对象有一指针指向可变大小的内存区域. 3.      对象机制的基石:PyObject 定长对象: typedef struct _object{ PyObject_HEAD }PyObject

《python源码剖析》笔记 python中的整数对象

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1. PyIntObject --> long的一个简单包装 typedef struct{ PyObject_HEAD long ob_ival; } PyIntObject; PyInt_Type --> PyIntObject的类型对象.与对象相关的元信息实际上都是保存在与对象对应的类型对象中的 PyTypeObject PyInt_Type = { PyObject_HEAD_I

《python源码剖析》笔记 python中的字符串对象

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.      PyStringObject --> 变长不可变对象 typedef struct{ PyObject_VAR_HEAD//ob_size变量保存着对象中维护的可变长度内存的大小 longob_shash; //缓存该对象的hash值,用于dict的查询 intob_sstate; //标志该对象是否经过intern机制的处理 char ob_sval[1];// 字符指针

[python 源码]字符串对象的实现

还是带着问题上路吧,和整数对象的实现同样的问题: >>> a='abc' >>> b='abc' >>> a is b True >>> c='abc'*10 >>> d='abc'*10 >>> d is c False why?在整数对象的实现中,对待小整数有小整数对象池,对待大整数对申请内存,字符串对象的实验也是这样的吗??? NO 先看下字符串对象的定义: typedef struct{ P

Python源码剖析笔记2-Python整数对象

Python源码剖析笔记2-Python整数对象 本文简书地址: http://www.jianshu.com/p/0136ed90cd46 千里之行始于足下,从简单的类别开始分析,由浅入深也不至于自己丧失信心.先来看看Python整数对象,也就是python中的PyIntObject对象,对应的类型对象是PyInt_Type. 1 Python整数对象概览 为了性能考虑,python中对小整数有专门的缓存池,这样就不需要每次使用小整数对象时去用malloc分配内存以及free释放内存.pyth

Python源码--整数对象(PyIntObject)的内存池

[背景] 原文链接:http://blog.csdn.net/ordeder/article/details/25343633 Python整数对象是不可变对象,什么意思呢?例如执行如下python语句 >>>a = 1023 >>>a = 1024 >>>b = a >>>c = 1024 >>>d = 195 >>>e = 195 python的整数对象结构为: typedef struct {