[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 ...
随机推荐
- 【转】Graphics.DrawImage 方法 IntPtr 结构 GDI 句柄 知识收集
Graphics.DrawImage 方法 在指定的位置使用原始物理大小绘制指定的 Image. 命名空间:System.Drawing 程序集:System.Drawing(在 system.dra ...
- 天梯赛 L2-024. (并查集) 部落
题目链接 题目描述 在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈.我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查 ...
- HDU 1181 变形课 (深搜)
题目连接 Problem Description 呃......变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的将一个棒球变成刺猬什么的,但是他发现了变形 ...
- 动态SQL中变量赋值
在动态SQL语句中进行变量的值绑定比较麻烦,这儿做个记录 declare @COUNT int,@sql nvarchar(max) set @sql = 'select @COUNT = count ...
- 2016.6.24——vector<vector<int>>【Binary Tree Level Order Traversal】
Binary Tree Level Order Traversal 本题收获: 1.vector<vector<int>>的用法 vector<vector<int ...
- KDE下安装fcitx后终端不能输入中文
编辑用户的 ~/.profile 文件(或/etc/profile): #fcitx export XIM_PROGRAM=fcitx export XIM=fcitx export GTK_IM_ ...
- FPGA设计方法检查表
-----------------------摘自<FPGA软件测试与评价技术> 中国电子信息产业发展研究院 | 编著------------------------------- 文本格 ...
- ARM Linux 3.x的设备树(Device Tree)【转】
转自:http://blog.csdn.net/21cnbao/article/details/8457546 宋宝华 Barry Song <21cnbao@gmail.com> 1. ...
- SQl 跨服务器查询脚本示例
1.采用OPENDATASOURCE select top 10 *from OPENDATASOURCE('SQLOLEDB','Data Source=IP地址;User ID=连接用户名称;Pa ...
- 怎么看innodb的B+TREE层数?
怎么看innodb的B+TREE层数?,下面以sysbench_testdata.sbtest2为例查看索引层数: - 查看相关系统 root@localhost [sysbench_testdata ...