PyObject对象机制的基石

学过Python的人应该非常清晰,Python中一切都是对象,全部的对象都有一个共同的基类,对于本篇博文来说,一切皆是对象则是探索Python的对象机制的一个入口点.我如果读者在阅读本文的时候已经下载Python(Python-2.7.11)的源代码,而且已经解压进入了源代码的根文件夹下.众所周知Python是用C实现的,C是一种OO的语言。而Python是一个OOP的语言,那么怎样在C语言层面实现OOP,实现多态,这是一个有意思的话题,这也是本文须要进行探索的点.Python内部使用了一个PyObject结构体来保存全部对象共同的数据成员,以及实现GC机制所须要的一些辅助字段等.所以能够说PyObject就是Python对象机制的基石。这毫不为过.那么让我们进入到源代码中.透过源代码看看Python中的对象究竟是个啥?

PyObject对象 

typedef struct _object {
PyObject_HEAD
} PyObject;

./Include/object.h

异常的简单,这一切都要归功于PyObject_HEAD宏,C语言中的宏是把双刃剑.看看PyObject_HEAD长什么样吧

#define PyObject_HEAD                   \
_PyObject_HEAD_EXTRA \
Py_ssize_t ob_refcnt; \
struct _typeobject *ob_type;

./Include/object.h

初看起来。还是不easy理解的,只是经验告诉我_PyObject_HEAD_EXTRA这个宏能够不用管。由于这是以下划线开头的,这类变量一般都是内部使用.为此我找到这个宏验证了我的想法.

/* Py_DEBUG implies Py_TRACE_REFS. */
#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS)
#define Py_TRACE_REFS
#endif /* Py_TRACE_REFS implies Py_REF_DEBUG. */
#if defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
#define Py_REF_DEBUG
#endif //注意看这里,仅仅有定义了Py_TRACE_REFS这个宏_PyObject_HEAD_EXTRA才不是空.
//而Py_TRACE_REFS这个宏仅仅有在Py_DEBUG有定义的情况下才会定义,可想而知 _PyObject_HEAD_EXTRA仅仅有在DEBUG模式
//才有意义,否则就是一个空.
#ifdef Py_TRACE_REFS
/* Define pointers to support a doubly-linked list of all live heap objects. */
#define _PyObject_HEAD_EXTRA \
struct _object *_ob_next; \
struct _object *_ob_prev; #define _PyObject_EXTRA_INIT 0, 0,
#else
#define _PyObject_HEAD_EXTRA
#define _PyObject_EXTRA_INIT
#endif

./Include/object.h

_PyObject_HEAD_EXTRA我们能够略过不看了,这个宏的作用仅仅是在DEBUG模式下,将全部的对象使用双链表链起来方便DEBUG而已.去掉_PyObject_HEAD_EXTRA后再来看看PyObject长啥样吧.

typedef struct _object {
Py_ssize_t ob_refcnt; \
struct _typeobject *ob_type;
} PyObject;

./Include/object.h

异常的清晰是不是,Py_ssize_t仅仅只是是对C语言的基本类型的一个typedef而已,这里能够觉得就是ssize_t类型了,ob_refcnt指的就是上文中说的GC机制须要的辅助字段用于维护当前对象的引用个数,ob_type是个啥呢?,这个东西说简单点就是指明当前对象是何种类型.后面会单独拿出来具体的介绍,接下来看下怎样使用PyObject来搭建整个Python的对象机制,以下是int对象的底层表示:

typedef struct {
PyObject_HEAD
long ob_ival;
} PyIntObject

./Include/intobject.h

包括了PyObject,除此之外包括了一些这些对象特有的一些数据成员,比方这里的ob_ival。就是用来保存int对象的具体数值的.那么String对象可想而知应该有一个char*的指针指向一段heap的内存空间,还须要有一个数据成员来保存当前的String的字符个数,那么list对象呢?,dict对象呢?,细想一下这些对象都应该包括一个指明当前对象包括的元素的个数的数据成员,好吧,这里我们找到了一些共同点。到这里产生了一个技术问题的抉择了,int对象不须要有指明当前对象包括元素个数的数据成员,而string对象,list对象,dict对象都须要有,那么这个数据成员应该放在PyObject中,还是归为每一个对象自己特有的数据成员呢?,Python选择了前者将这个数据成员放到了PyObject中。但又没全然这样做.这一切都归功于Python中的另外一个概念,可变对象和不可变对象.以下通过源代码我们来看看Python究竟是怎么做的

PyVarObject对象

typedef struct {
PyObject_VAR_HEAD
} PyVarObject;

./Include/object.h

弄了一个PyVarObject对象出来了,事实上这是一个所谓的纸老虎。打开PyObject_VAR_HEAD这个宏你就会发现真相原来是这样.

#define PyObject_VAR_HEAD               \
PyObject_HEAD \
Py_ssize_t ob_size; /* Number of items in variable part */

./Include/object.h

又是异常的简单。就是在原有的PyObject基础上加了一个ob_size成员,用来指明当前对象所拥有的元素个数.可是有一个须要注意就是ob_size数据成员的位置仅仅能在PyObject_HEAD以下,目的是为了能够通过PyObject强制转换成不论什么一个对象.如果你不明确,那么来张图看看.

回到Python

源代码看完了,是不是有点想大展宏图的冲动。可惜依照我们眼下的水平。相对Python做些什么恐怕还不够格。只是我们能够利用Python来验证下我们读源代码的收获.通过上文分析的PyObject,还有PyIntObject。我们来计算一下一个PyIntObject大小。

typedef struct {
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
long ob_ival;
} PyIntObject

一个ob_refcnt这是一个ssize_t类型,64为系统下是8个字节,一个ob_type是个指针,在64位系统下相同也是8个字节,一个long类型在64位系统下相同也是8个字节所以算起来一个PyIntObject是24个字节,回到Python中我们来验证一下:

>>> import sys
>>> inttype = 1
>>> sys.getsizeof(inttype)
24

Python内部机制-PyObject对象的更多相关文章

  1. Python内部机制。

    type ,object ,__class__ ,__bases__ ,__metaclass__ , -------------------------不明白的地方----------------- ...

  2. 从底层带你理解Python中的一些内部机制

    下面博文将带你创建一个字节码级别的追踪API以追踪Python的一些内部机制,比如类似YIELDVALUE.YIELDFROM操作码的实现,推式构造列表(List Comprehensions).生成 ...

  3. Python_Mix*函数名的使用以及第一类对象,闭包,迭代器,for循环的内部机制

    一:函数名的应用(第一类对象) 函数名的命名规范和变量是一样的,函数名其实就是变量名, 0)函数名可以赋值给其他变量 def func(): #定义一个名为func的函数 print('my ange ...

  4. python与java的内存机制不一样;java的方法会进入方法区直到对象消失 方法才会消失;python的方法是对象每次调用都会创建新的对象 内存地址都不i一样

    python与java的内存机制不一样;java的方法会进入方法区直到对象消失 方法才会消失;python的方法是对象每次调用都会创建新的对象 内存地址都不i一样

  5. 《python解释器源码剖析》第6章--python中的dict对象

    6.0 序 元素和元素之间可能存在着某种关系,比如学生姓名和成绩.我希望能够通过学生的姓名找到这个学生的成绩,那么只需要将两者关联起来即可.字典正是这么做的,字典中的每个元素就是一个key:value ...

  6. 万字综述,核心开发者全面解读PyTorch内部机制

    斯坦福大学博士生与 Facebook 人工智能研究所研究工程师 Edward Z. Yang 是 PyTorch 开源项目的核心开发者之一.他在 5 月 14 日的 PyTorch 纽约聚会上做了一个 ...

  7. Python入门笔记(5):对象

    一.学习目录 1.pyhton对象 2.python类型 3.类型操作符与内建函数 4.类型工厂函数 5.不支持类型 二.思考 1.Python解释执行原理? 2.Python对象机制? 3.Pyth ...

  8. python多线程机制

    Python中的线程从一开始就是操作系统的原生线程.而Python虚拟机也同样使用一个全局解释器锁(Global Interpreter Lock,GIL)来互斥线程多Python虚拟机的使用. GI ...

  9. 【Python&数据结构】 抽象数据类型 Python类机制和异常

    这篇是<数据结构与算法Python语言描述>的笔记,但是大头在Python类机制和面向对象编程的说明上面.我也不知道该放什么分类了..总之之前也没怎么认真接触过基于类而不是独立函数的Pyt ...

随机推荐

  1. React Native入门——IDE及其它相关基础技术

    关于React Native的开发,当中一个问题是缺少好用的IDE,有些人说不就是JS么,搞一个记事本也就写了,那样尽管牛逼,但事实上还是非常头大的,有一款好的IDE还是能提升开发效率的,这里对几个还 ...

  2. 云计算时代告别phpMyAdmin

    云计算时代告别phpMyAdmin phpMyAdmin是一款很经典的MySQL数据库管理工具,在云计算快速发展的今天,phpMyAdmin交互老旧.已经不能适应时代步伐.因此有很多人開始选择一些更高 ...

  3. solr 亿万级数据查询性能測试

    废话不多说,我电脑配置 i7四核cpu 8G内存 插入数据文档中有5个字段,当中有两个分词.一个int,一个date 批量插入測试一次10万循环10次总共100万用时85秒 批量插入測试一次10万循环 ...

  4. Python: PS 滤镜特效 -- Marble Filter

    本文用 Python 实现 PS 滤镜特效,Marble Filter, 这种滤镜使图像产生不规则的扭曲,看起来像某种玻璃条纹, 具体的代码如下: import numpy as np import ...

  5. Mysql数据库调优和性能优化

    1. 简介 在Web应用程序体系架构中,数据持久层(通常是一个关系数据库)是关键的核心部分,它对系统的性能有非常重要的影响.MySQL是目前使用最多的开源数据库,但是mysql数据库的默认设置性能非常 ...

  6. 【Codeforces Round #456 (Div. 2) B】New Year's Eve

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 显然10000..取到之后 再取一个01111..就能异或成最大的数字了. [代码] /* 1.Shoud it use long ...

  7. mvc定时执行任务(获取气象台的气象数据,定时新增)

    1.定时任务: gloabl.asax文件Application_Start()方法注册: System.Timers.Timer t = new System.Timers.Timer(theInt ...

  8. JAVA Mail邮件实现发送

    package com.test;import java.util.Date;import java.util.Properties;import javax.mail.Message;import ...

  9. flex布局:

    他的布局主要有两个“二”,一个二:容器项,子项目项.另一个:有两条轴,主轴,副轴.它的使用时,必须先声明说明是flex布局:display:flex; 针对于容器项的属性6个: 1.flex-dire ...

  10. JavaScript--数据结构之栈

    4.1栈是一种高效的数据结构,是一种特殊的列表.栈内元素只能通过列表的一端访问,也就称为栈顶.后入的先出的操作.Last in First out.所以他的访问每次是访问到栈顶的元素,要想访问其余的元 ...