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

  现在还记得刚开始学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]源码-对象的创建和行为的更多相关文章

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

    刚开始学python时候,发现一个很迷惑的现象,一直到看了源码后才知道了: >>> a=6 >>> b=6 >>> a is b True 想用同 ...

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

    还是带着问题上路吧,和整数对象的实现同样的问题: >>> a='abc' >>> b='abc' >>> a is b True >> ...

  3. Python 源码剖析(一)【python对象】

    处于研究python内存释放问题,在阅读部分python源码,顺便记录下所得.(基于<python源码剖析>(v2.4.1)与 python源码(v2.7.6)) 先列下总结:      ...

  4. Python源码剖析——01内建对象

    <Python源码剖析>笔记 第一章:对象初识 对象是Python中的核心概念,面向对象中的"类"和"对象"在Python中的概念都为对象,具体分为 ...

  5. Python源码中的PyCodeObject

    1.Python程序的执行过程 Python解释器(interpreter)在执行任何一个Python程序文件时,首先进行的动作都是先对文件中的Python源代码进行编译,编译的主要结果是产生的一组P ...

  6. python源码学习(一)——python的总体架构

    python源码学习(一)——python的总体架构 学习环境: 系统:ubuntu 12.04 STLpython版本:2.7既然要学习python的源码,首先我们要在电脑上安装python并且下载 ...

  7. Python源码分析(一)

    最近想学习下Python的源码,希望写个系列博客,记录的同时督促自己学习. Python源码目录 从Python.org中下载源代码压缩包并解压,我下载的是Python2.7.12,解压后: 对于主要 ...

  8. Python 源码剖析(六)【内存管理机制】

    六.内存管理机制 1.内存管理架构 2.小块空间的内存池 3.循环引用的垃圾收集 4.python中的垃圾收集 1.内存管理架构 Python内存管理机制有两套实现,由编译符号PYMALLOC_DEB ...

  9. Python 源码学习之内存管理 -- (转)

    Python 的内存管理架构(Objects/obmalloc.c): _____ ______ ______ ________ [ int ] [ dict ] [ list ] ... [ str ...

随机推荐

  1. 【leetcode 简单】 第八十八题 猜数字大小

    我们正在玩一个猜数字游戏. 游戏规则如下: 我从 1 到 n 选择一个数字. 你需要猜我选择了哪个数字. 每次你猜错了,我会告诉你这个数字是大了还是小了. 你调用一个预先定义好的接口 guess(in ...

  2. 树形dp&&树的重心(D - Godfather POJ - 3107)

    题目链接:https://cn.vjudge.net/contest/277955#problem/D 题目大意:求树的重心(树的重心指的是树上的某一个点,删掉之后形成的多棵树中节点数最大值最小). ...

  3. [转]使用 C++11 编写 Linux 多线程程序

    前言 在这个多核时代,如何充分利用每个 CPU 内核是一个绕不开的话题,从需要为成千上万的用户同时提供服务的服务端应用程序,到需要同时打开十几个页面,每个页面都有几十上百个链接的 web 浏览器应用程 ...

  4. Electron 开发环境下总是 crash

    全局安装一个 electron devtool 关掉 崩溃时选择重新打开

  5. 2016.07.15——istringstream测试

    istringstream测试 1.istringstream strcin(str),字符串(str)可以包括多个单词,单词之间使用空格分开 #include "stdafx.h" ...

  6. ORA-00906 missing left parenthesis括号

    Oracle 建表报错:ORA-00906 missing left parenthesis括号    建表语句:create table test(id char,name varchar(1),s ...

  7. 2017-2018-2 20179205《网络攻防技术与实践》第十一周作业 SQL注入攻击与实践

    <网络攻防技术与实践>第十一周作业 SQL注入攻击与实践 1.研究缓冲区溢出的原理,至少针对两种数据库进行差异化研究 缓冲区溢出原理   在计算机内部,输入数据通常被存放在一个临时空间内, ...

  8. Fiddler是最强大最好用的Web调试工具

    Fiddler是最强大最好用的Web调试工具之一,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据. 使用Fiddler无论对开发还是测试来说,都有很大 ...

  9. RestTemplate中文乱码问题(spring-web3.0.7版本)

    从网上找的方法: 方法一: //resttemplate乱码问题 //3.1.X以上版本使用 // restTemplate.getMessageConverters().add(0, StringH ...

  10. docker stack 部署 filebeat

    =============================================== 2018/7/21_第3次修改                       ccb_warlock 更新 ...