q3256 发表于 2017-4-29 14:28:56

[Python源码学习]之PyObject和PyTypeObject

Python C api中的绝大多数函数其参数和返回值中包含PyObject*。这指针类型指向一个可以表示任何Python对象的不透明的数据结构。所有的Python对象在多数情况下以相同的方式对待。
所有的Python对象(甚至是Python的整数)都包含一个类型和引用计数。一个对象的类型决定了其是一个整数、列表、用户自定义函数还是其他。
引用计数对Python非常重要,引用计数必须显式地操作(通过Py_INCREF()、 Py_DECREF()等)。
本文:


[*]

PyObject

[*]

PyVarObject

[*]

PyTypeObject



PyObject


Include/object.h 提供了比较详细的注释。


[*]

PyObject 本身几乎没有声明任何东西,但是每一个Python对象的指针都可以cast为PyObject* 。类似地,每一个大小不固定的Python对象指针可以cast为 PyVarObject* 。

[*]

PyObject_HEAD 定义了每一个PyObject都有的起始片段。

[*]Python2.7和Python3.2中,尽管内容一样,但源码的写法上有点小小的不同:

Python2.7


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

Python3.2


typedef struct _object {
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;
#define PyObject_HEAD PyObject ob_base;

PyObject 是有两个成员的结构体,引用计数、对象类型:


[*]ob_refcnt
[*]ob_type

其类型分别为 Py_ssize_t 和 struct _typeobject


Py_ssize_t


Py_ssize_t 是一个所占字节数与 size_t 相同的有符号的整数类型(C99中没有定义ssize_t这种类型,某些编译器比如gcc扩展有该类型)。关于该类型的一个介绍见PEP
353。
源码位于:Include/pyport.h


#ifdef HAVE_SSIZE_T
typedef ssize_t         Py_ssize_t;
#elif SIZEOF_VOID_P == SIZEOF_SIZE_T
typedef Py_intptr_t   Py_ssize_t;
#else
#   error "Python needs a typedef for Py_ssize_t in pyport.h."
#endif

其中,Py_intptr_t 是可以存放指针的整数类型(C99中定义有 intptr_t),在不支持intptr_t的环境下,它是int、long或long long的别名。


PyVarObject


可变大小的容器对象
与PyObject相比,它多了一个成员:


[*]ob_refcnt
[*]ob_type
[*]ob_size

其中:ob_size 是元素的数目,而不是所需的字节的数目。
Python2.7

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

typedef struct {
    PyObject_VAR_HEAD
} PyVarObject;

Python3.2

typedef struct {
    PyObject ob_base;
    Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
#define PyObject_VAR_HEAD      PyVarObject ob_base;

3个宏用来获取这3个成员的值

#define Py_REFCNT(ob)         (((PyObject*)(ob))->ob_refcnt)
#define Py_TYPE(ob)             (((PyObject*)(ob))->ob_type)
#define Py_SIZE(ob)             (((PyVarObject*)(ob))->ob_size)


PyTypeObject


每一个PyObject第二个成员是都是一个类型对象(PyTypeObject)。PyTypeObject本身是也一个PyVarObject
额,这个东西太复杂了,一堆堆的函数指针,看不懂。

typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; /* For printing, in format "<module>.<name>" */
    Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

    /* Methods to implement standard operations */

    destructor tp_dealloc;
    printfunc tp_print;
    getattrfunc tp_getattr;
    setattrfunc tp_setattr;
    void *tp_reserved; /* formerly known as tp_compare */
    reprfunc tp_repr;
...
} PyTypeObject;





tp_name




类型的字符串名,比如"str" "int" ...







tp_basicsize




tp_basesize + tp_tiemsize * ob_size







tp_itemsize







tp_doc




文档字符串







创建与析构?





tp_alloc







tp_new







tp_init







tp_del







tp_free







tp_dealloc







C API函数和这些函数指针的对应关系(调用关系):





C API函数




PyTypeObject

中的函数指针




Python表达式







PyObject_Print(PyObject*,FILE*,int)




tp_print

tp_str

tp_repr









PyObject_Repr(PyObject*)




tp_repr




repr(o)







PyObject_Str(PyObject*v)




tp_str




str(o)







PyObject_Hash(PyObject*)




tp_hash




hash(o)







PyObject_GetAttr(PyObject*,PyObject*)




tp_getattr

tp_getattro




o.attr_name







PyObject_CallMethod(PyObject*,char*,...)




tp_call




o.method(...)







...












参考



[*]

http://docs.python.org/py3k/c-api/object.html

[*]

http://docs.python.org/py3k/c-api/intro.html#objects-types-and-reference-counts

[*]

http://docs.python.org/py3k/c-api/structures.html

[*]

http://docs.python.org/py3k/c-api/typeobj.html

页: [1]
查看完整版本: [Python源码学习]之PyObject和PyTypeObject