[python]源码-对象的创建和行为
(明天论文就要送审了!!!距离毕业一个月!!!)
现在还记得刚开始学python时候被这种动态语言惊到的那种感觉,列表和字典对象可以随意伸缩,简直不能更帅了,但是一直不知道内部到底是怎么实现的,python源码用C实现的,但是C是过程性语言啊。
说怎么实现之前,先捋捋什么是对象,对这个我觉得《python源码剖析》这本书里面的解释很有意思:“一个对象实际上就是一片被分配的内存空间,这些内存可能是连续的,也可能是不连续的,这都不重要,重要的是这片内存在更高的层次上可以作为一个整体来考虑,这个整体就是对象,在这片内存中,存储着一系列的数据以及可以对这些数据进行修改和读取操作的代码”,一个很有意思的角度。
一个对象被创建后,它所占用的内存大小就是不可变的了,这意味着对可变长度的数据来说(比如字符串),只能在对象内部维护一个指向可变大小内存区域的指针。
在python中,一切皆是对象,其中所有对象的核心就是一个叫PyObject的结构体
typedef struct _object{
int ob_refcnt;
struct _typeobject *ob_type;
}PyObject;
其中,ob_refcnt为引用计数,_typeobject决定了对象的类型,ob_type指向了一个类型对象(我的理解:基类),这个结构体将出现在所有对象所占有内存的最开始的地方,就比如在一个int类中:
typedef struct{
PyObject _HEAD;
long ob_ival;
}PyIntObject;
int值得信息就保存在ob_ival中,这是python2.5中的int对象,如果是list这种可变长度的对象,这种方法显然是不行的,那么就把头部结构体PyObject中加一个表示此对象占有多少个对象的信息ob_size,这个值也就表明了边长对象中一共有多少个元素:
#define PyObject_VAR_HEAD
PyObject_HEAD
int ob_size; typedef struct{
PyObject_VAR_HEAD
}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源码剖析
[python]源码-对象的创建和行为的更多相关文章
- [python 源码]整数对象的创建和维护
刚开始学python时候,发现一个很迷惑的现象,一直到看了源码后才知道了: >>> a=6 >>> b=6 >>> a is b True 想用同 ...
- [python 源码]字符串对象的实现
还是带着问题上路吧,和整数对象的实现同样的问题: >>> a='abc' >>> b='abc' >>> a is b True >> ...
- Python 源码剖析(一)【python对象】
处于研究python内存释放问题,在阅读部分python源码,顺便记录下所得.(基于<python源码剖析>(v2.4.1)与 python源码(v2.7.6)) 先列下总结: ...
- Python源码剖析——01内建对象
<Python源码剖析>笔记 第一章:对象初识 对象是Python中的核心概念,面向对象中的"类"和"对象"在Python中的概念都为对象,具体分为 ...
- Python源码中的PyCodeObject
1.Python程序的执行过程 Python解释器(interpreter)在执行任何一个Python程序文件时,首先进行的动作都是先对文件中的Python源代码进行编译,编译的主要结果是产生的一组P ...
- python源码学习(一)——python的总体架构
python源码学习(一)——python的总体架构 学习环境: 系统:ubuntu 12.04 STLpython版本:2.7既然要学习python的源码,首先我们要在电脑上安装python并且下载 ...
- Python源码分析(一)
最近想学习下Python的源码,希望写个系列博客,记录的同时督促自己学习. Python源码目录 从Python.org中下载源代码压缩包并解压,我下载的是Python2.7.12,解压后: 对于主要 ...
- Python 源码剖析(六)【内存管理机制】
六.内存管理机制 1.内存管理架构 2.小块空间的内存池 3.循环引用的垃圾收集 4.python中的垃圾收集 1.内存管理架构 Python内存管理机制有两套实现,由编译符号PYMALLOC_DEB ...
- Python 源码学习之内存管理 -- (转)
Python 的内存管理架构(Objects/obmalloc.c): _____ ______ ______ ________ [ int ] [ dict ] [ list ] ... [ str ...
随机推荐
- 奇怪的C代码
; int ans = (++i)+(++i)+(++i); ans等于多少?我想大多数同学都会和我一样的认为: ans = 4 + 5 + 6 = 15. 而实际结果呢? - Linux下用gcc编 ...
- vue_router 动态路由
配置子路由: 路由的视图都需要使用view-router 子路由也可以嵌套路由使用: children来做嵌套如上图 使用location.页面name就可以做页面跳转 mounted:挂载,延迟跳转 ...
- Linux内核跟踪之ring buffer的实现【转】
转自:http://blog.chinaunix.net/uid-20543183-id-1930845.html ---------------------------------------- ...
- Fiddler大师之路系列(一)
江湖传言,Fiddler是捕获客户端与服务器之间的所有HTTP(S) 请求的利器,但是在具体使用过程中,发现使用Fiddler进行抓包时有一部分请求总是没到,多方苦寻之下发现客户端使用WinINET这 ...
- ASP.NET MVC 防止跨站请求伪造(CSRF)攻击的方法
在HTTP POST请求中,我们多次在View和Controller中看下如下代码: View中调用了Html.AntiForgeryToken(). Controller中的方法添加了[Valida ...
- [转] Cacti+Nagios监控平台完美整合
Cacti+Nagios监控平台完美整合 http://os.51cto.com/art/201411/458006.htm 整合nagios+cacti+微信.飞信实现网络监控报警 http://b ...
- JAVA随笔(三)
私有是针对类的,而不是对象. static 函数,其实是类函数.之前一直不太理解每个类中的static main是什么意思,为什么main中不能直接调用非静态的变量:因为main是 类函数,不是属于某 ...
- 洛谷P3378堆
传送门啦 #include <iostream> #include <cstdio> #include <cstring> #include <algorit ...
- 洛谷P2024食物链
传送门啦 这道题的特殊之处在于对于任意一个并查集,只要告诉你某个节点的物种,你就可以知道所有节点对应的物种. 比如一条长为4的链 甲->乙->丙->丁 ,我们知道乙是A物种.那么甲一 ...
- 洛谷P3760异或和
传送门啦 传送门啦 一般这种位运算的题都要把每一位拆开来看,因为位运算每个位的结果这和这一位的数有关. 这样我们用s[i]表示a的前缀和,即 $ a[1]+a[2]+....a[i] $ ,然后我们从 ...