python源码学习笔记(一)
2013-01-10 09:34
393 查看
(一)python对象的基本实现
众所周之,python是个极其简洁高效的脚本语言,其设计思维之简洁,编写之简单,已成公认。想着深入了解内部机制,探索一下源代码,并记录一些东西。诚然,人总是健忘的,因而只有不断地写日记和笔记记录自己的想法,我们的有益的想法和生活的点滴才能被永久地保存下来,否者只能在别人思想的轨道上空转,始终成为不了自己的东西。
当然对于现存的事物,我们最好或者一定要采取critica thingking的态度。准备考试,最大的痛苦就是要照抄全搬,头脑越学越死。当时归根到底我们学习不是为了考试,不是为了分数,更重要的是提高自己的capability。
python源码的注释很清楚,或者说很人性化,而且事实上也不会出现艰难晦涩的算法,最主要的还是设计的思想和框架。当然宏神马的很讨厌,窜来窜去的...
学习python的第一步就是要了解其工作机制,下面开始记录:
所谓对象,实际上是把一块数据集及针对数据的操作当做为一个整体,非常符合人的思维,比如开关灯,灯、开关就是数据,打开开关就是操作。
首先,python都有个根对象即PyObject, 采用引用计数的方式,当ob_refcnt=0时,从堆中删除对象,释放出内存供别的对象使用。对于可变大小的Object称为PyVarObject, 这样的对象通常都是Container, 在PyObject_VAR_HEAD中有个ob_size这个变量,表明有多少个对象在容器中。具体定义如下
python 中还有一个比较关键的就是类型对象的定义,像C里面有内置的int , double 一样,python 里也需要内置的对象
接着我们会看到_typeobject 的定义
与类型相关联的操作信息一般采取函数指针的形式 ,例如 typedef long (*hashfunc)(PyObject *);这些操作分为 标准操作(dealloc, print , compare),标准操作族(numbers, sequences, mappings) 以及其他操作(hash, buff, call)
另外,值得我们注意的是_typeobject也是个对象,其类型为PyType_Type
紧接着我们会留意到针对PyObject一系列的宏,首先是:
第一个是新建对象引用,即初始化ob_refcnt=1,很有意思哈,连comma——','都被宏定义了,然后是丢弃对象引用:
然后是对对象引用的自增、自减操作。当ob_refcnt=0时,调用析构函数,即tp_dealloc。另外如果OP是个NIL,必须使用Py_XINCREF/Py_XDECREF。基本非常基础的内容,比较浅显,是python设计的开始,和MFC的原理有点类似,PyObject对应CObject。
众所周之,python是个极其简洁高效的脚本语言,其设计思维之简洁,编写之简单,已成公认。想着深入了解内部机制,探索一下源代码,并记录一些东西。诚然,人总是健忘的,因而只有不断地写日记和笔记记录自己的想法,我们的有益的想法和生活的点滴才能被永久地保存下来,否者只能在别人思想的轨道上空转,始终成为不了自己的东西。
当然对于现存的事物,我们最好或者一定要采取critica thingking的态度。准备考试,最大的痛苦就是要照抄全搬,头脑越学越死。当时归根到底我们学习不是为了考试,不是为了分数,更重要的是提高自己的capability。
python源码的注释很清楚,或者说很人性化,而且事实上也不会出现艰难晦涩的算法,最主要的还是设计的思想和框架。当然宏神马的很讨厌,窜来窜去的...
学习python的第一步就是要了解其工作机制,下面开始记录:
所谓对象,实际上是把一块数据集及针对数据的操作当做为一个整体,非常符合人的思维,比如开关灯,灯、开关就是数据,打开开关就是操作。
首先,python都有个根对象即PyObject, 采用引用计数的方式,当ob_refcnt=0时,从堆中删除对象,释放出内存供别的对象使用。对于可变大小的Object称为PyVarObject, 这样的对象通常都是Container, 在PyObject_VAR_HEAD中有个ob_size这个变量,表明有多少个对象在容器中。具体定义如下
[object.h] #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 /* PyObject_HEAD defines the initial segment of every PyObject. */ #define PyObject_HEAD \ _PyObject_HEAD_EXTRA \ Py_ssize_t ob_refcnt; \ //引用计数 struct _typeobject *ob_type; #define PyObject_HEAD_INIT(type) \ _PyObject_EXTRA_INIT \ 1, type, #define PyVarObject_HEAD_INIT(type, size) \ PyObject_HEAD_INIT(type) size, .... typedef struct _object { PyObject_HEAD } PyObject; typedef struct { PyObject_VAR_HEAD } PyVarObject;
python 中还有一个比较关键的就是类型对象的定义,像C里面有内置的int , double 一样,python 里也需要内置的对象
接着我们会看到_typeobject 的定义
[object.h] typedef struct _typeobject{ PyObject_VAR_HEAD //注意这里也有对象头 char *tp_name; //for printing int tp_basicsize, tp_itmesize; //methods destructor tp_dealloc; printfunc tp_print; ..... //more hashfunc tp_hash; ternaryfunc tp_call; .... } PyTypeObject;
与类型相关联的操作信息一般采取函数指针的形式 ,例如 typedef long (*hashfunc)(PyObject *);这些操作分为 标准操作(dealloc, print , compare),标准操作族(numbers, sequences, mappings) 以及其他操作(hash, buff, call)
另外,值得我们注意的是_typeobject也是个对象,其类型为PyType_Type
[typeobject.c] PyTypeObject PyType_Type ={ PyObject_HEAD_INIT(&PyType_Type) 0, "type", sizeof(PyHeadTypeObject), sizeof(PyMemberDef), .... PyObject_GC_Del, (inquiry) type_is_gc, }; //以一个整数对象为例: PyTypeObject PyInt_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, "int", sizeof(PyIntObject), ... };
紧接着我们会留意到针对PyObject一系列的宏,首先是:
#define _Py_NewReference(op) ( \ _Py_INC_TPALLOCS(op) _Py_COUNT_ALLOCS_COMMA \ _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \ Py_REFCNT(op) = 1) #define _Py_ForgetReference(op) _Py_INC_TPFREES(op) #define _Py_Dealloc(op) ( \ _Py_INC_TPFREES(op) _Py_COUNT_ALLOCS_COMMA \ (*Py_TYPE(op)->tp_dealloc)((PyObject *)(op))) #endif /* !Py_TRACE_REFS */ #define Py_INCREF(op) ( \ _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \ ((PyObject*)(op))->ob_refcnt++) #define Py_DECREF(op) \ do { \ if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \ --((PyObject*)(op))->ob_refcnt != 0) \ _Py_CHECK_REFCNT(op) \ else \ _Py_Dealloc((PyObject *)(op)); \ } while (0)
第一个是新建对象引用,即初始化ob_refcnt=1,很有意思哈,连comma——','都被宏定义了,然后是丢弃对象引用:
#define _Py_INC_TPFREES(OP) dec_count(Py_TYPE(OP))
然后是对对象引用的自增、自减操作。当ob_refcnt=0时,调用析构函数,即tp_dealloc。另外如果OP是个NIL,必须使用Py_XINCREF/Py_XDECREF。基本非常基础的内容,比较浅显,是python设计的开始,和MFC的原理有点类似,PyObject对应CObject。
相关文章推荐
- Python源码分析--学习笔记一
- Python源码学习笔记 4 列表对象
- Python2学习笔记之实现ping和which源码
- Python源码学习笔记 3 字符串对象
- Python源码学习笔记 1 简述python对象
- Python爬虫框架Scrapy 学习笔记 7------- scrapy.Item源码剖析
- 《统计学习方法》-支持向量机SVM学习笔记和python源码
- Python源码学习笔记(1 基本数据类型)
- Python源码学习笔记 2 整数对象
- Python学习笔记之递归
- python学习笔记-(12)python中模块的概念
- python核心编程学习笔记-2016-08-13-05-property()函数
- Python学习笔记01 从零开始Hello world
- python学习笔记-(14)python循环中的高级用法
- python 学习笔记1
- 学习笔记☞ python 基础(python3)【五】(模块,面向对象编程-1)
- Python学习笔记——常量定义
- python核心编程学习笔记-2016-09-25-01-python扩展
- Python 3.6学习笔记(一)
- python 学习笔记 8 -- Python下调用Linux的Shell命令