python源码学习笔记(一)

 (一)python对象的基本实现
 
      众所周之,python是个极其简洁高效的脚本语言,其设计思维之简洁,编写之简单,已成公认。想着深入了解内部机制,探索一下源代码,并记录一些东西。诚然,人总是健忘的,因而只有不断地写日记和笔记记录自己的想法,我们的有益的想法和生活的点滴才能被永久地保存下来,否者只能在别人思想的轨道上空转,始终成为不了自己的东西。
    当然对于现存的事物,我们最好或者一定要采取critica thingking的态度。准备考试,最大的痛苦就是要照抄全搬,头脑越学越死。当时归根到底我们学习不是为了考试,不是为了分数,更重要的是提高自己的capability。
    python源码的注释很清楚,或者说很人性化,而且事实上也不会出现艰难晦涩的算法,最主要的还是设计的思想和框架。当然宏神马的很讨厌,窜来窜去的...
    学习python的第一步就是要了解其工作机制,下面开始记录:
    所谓对象,实际上是把一块数据集及针对数据的操作当做为一个整体,非常符合人的思维,比如开关灯,灯、开关就是数据,打开开关就是操作。
首先,python都有个根对象即PyObject, 采用引用计数的方式,当ob_refcnt=0时,从堆中删除对象,释放出内存供别的对象使用。对于可变大小的Object称为PyVarObject, 这样的对象通常都是Container, 在PyObject_VAR_HEAD中有个ob_size这个变量,表明有多少个对象在容器中。具体定义如下
 1 [object.h]
 2 #ifdef Py_TRACE_REFS
 3 /* Define pointers to support a doubly-linked list of all live heap objects. */
 4 #define _PyObject_HEAD_EXTRA            \
 5     struct _object *_ob_next;           \
 6     struct _object *_ob_prev;
 7  
 8 #define _PyObject_EXTRA_INIT 0, 0,
 9  
10 #else
11 #define _PyObject_HEAD_EXTRA
12 #define _PyObject_EXTRA_INIT
13 #endif
14  
15 /* PyObject_HEAD defines the initial segment of every PyObject. */
16 #define PyObject_HEAD                   \
17     _PyObject_HEAD_EXTRA                \
18     Py_ssize_t ob_refcnt;               \            //引用计数
19     struct _typeobject *ob_type;
20  
21 #define PyObject_HEAD_INIT(type)        \
22     _PyObject_EXTRA_INIT                \
23     1, type,
24  
25 #define PyVarObject_HEAD_INIT(type, size)       \
26     PyObject_HEAD_INIT(type) size,
27 ....
28  
29 typedef struct _object {
30     PyObject_HEAD
31 } PyObject;
32  
33 typedef struct {
34     PyObject_VAR_HEAD
35 } PyVarObject;

 

 
 
       python 中还有一个比较关键的就是类型对象的定义,像C里面有内置的int , double 一样,python 里也需要内置的对象
接着我们会看到_typeobject 的定义
 1 [object.h]
 2 typedef struct _typeobject{
 3     PyObject_VAR_HEAD            //注意这里也有对象头
 4     char *tp_name;                        //for printing 
 5     int tp_basicsize, tp_itmesize;
 6  
 7  
 8     //methods
 9     destructor tp_dealloc;
10     printfunc   tp_print;
11     .....
12  
13  
14    //more 
15     hashfunc   tp_hash;
16     ternaryfunc  tp_call;
17     ....
18  
19 }  PyTypeObject;

 

     与类型相关联的操作信息一般采取函数指针的形式 ,例如  typedef long (*hashfunc)(PyObject *);这些操作分为  标准操作(dealloc, print , compare),标准操作族(numbers, sequences, mappings) 以及其他操作(hash, buff, call)
 
     另外,值得我们注意的是_typeobject也是个对象,其类型为PyType_Type
 
 1 [typeobject.c]
 2  
 3 PyTypeObject PyType_Type ={
 4     PyObject_HEAD_INIT(&PyType_Type)
 5     0,
 6     "type",
 7     sizeof(PyHeadTypeObject),
 8     sizeof(PyMemberDef),
 9     ....
10     PyObject_GC_Del,
11     (inquiry) type_is_gc,
12  
13 };
14 //以一个整数对象为例:
15 PyTypeObject  PyInt_Type = {
16     PyObject_HEAD_INIT(&PyType_Type)
17     0,
18     "int",
19     sizeof(PyIntObject),
20     ...
21 };

 

 
     紧接着我们会留意到针对PyObject一系列的宏,首先是:
 1 #define _Py_NewReference(op) (                          \
 2     _Py_INC_TPALLOCS(op) _Py_COUNT_ALLOCS_COMMA         \
 3     _Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA               \
 4     Py_REFCNT(op) = 1)
 5  
 6 #define _Py_ForgetReference(op) _Py_INC_TPFREES(op)
 7  
 8 #define _Py_Dealloc(op) (                               \
 9     _Py_INC_TPFREES(op) _Py_COUNT_ALLOCS_COMMA          \
10     (*Py_TYPE(op)->tp_dealloc)((PyObject *)(op)))
11 #endif /* !Py_TRACE_REFS */
12  
13 #define Py_INCREF(op) (                         \
14     _Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA       \
15     ((PyObject*)(op))->ob_refcnt++)
16  
17 #define Py_DECREF(op)                                   \
18     do {                                                \
19         if (_Py_DEC_REFTOTAL  _Py_REF_DEBUG_COMMA       \
20         --((PyObject*)(op))->ob_refcnt != 0)            \
21             _Py_CHECK_REFCNT(op)                        \
22         else                                            \
23         _Py_Dealloc((PyObject *)(op));                  \
24     } while (0)
25  

 

 
     第一个是新建对象引用,即初始化ob_refcnt=1,很有意思哈,连comma——','都被宏定义了,然后是丢弃对象引用:
1 #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。

posted @ 2013-01-10 09:34  happydpc  阅读(504)  评论(0编辑  收藏  举报