[Python源码学习]之PyObject和PyTypeObject
2011-08-13 12:26
645 查看
Python C api中的绝大多数函数其参数和返回值中包含 PyObject*。这指针类型指向一个可以表示任何Python对象的不透明的数据结构。所有的Python对象在多数情况下以相同的方式对待。
所有的Python对象(甚至是Python的整数)都包含一个类型和引用计数。一个对象的类型决定了其是一个整数、列表、用户自定义函数还是其他。
引用计数对Python非常重要,引用计数必须显式地操作(通过Py_INCREF()、 Py_DECREF()等)。
本文:
PyObject
PyVarObject
PyTypeObject
Include/object.h 提供了比较详细的注释。
PyObject 本身几乎没有声明任何东西,但是每一个Python对象的指针都可以cast为PyObject* 。类似地,每一个大小不固定的Python对象指针可以cast为 PyVarObject* 。
PyObject_HEAD 定义了每一个PyObject都有的起始片段。
Python2.7和Python3.2中,尽管内容一样,但源码的写法上有点小小的不同:
Python2.7
Python3.2
PyObject 是有两个成员的结构体,引用计数、对象类型:
ob_refcnt
ob_type
其类型分别为 Py_ssize_t 和 struct _typeobject
Py_ssize_t 是一个所占字节数与 size_t 相同的有符号的整数类型(C99中没有定义ssize_t这种类型,某些编译器比如gcc扩展有该类型)。关于该类型的一个介绍见PEP
353。
源码位于:Include/pyport.h
其中,Py_intptr_t 是可以存放指针的整数类型(C99中定义有 intptr_t),在不支持intptr_t的环境下,它是int、long或long long的别名。
可变大小的容器对象
与PyObject相比,它多了一个成员:
ob_refcnt
ob_type
ob_size
其中:ob_size 是元素的数目,而不是所需的字节的数目。
Python2.7
Python3.2
3个宏用来获取这3个成员的值
每一个PyObject第二个成员是都是一个类型对象(PyTypeObject)。PyTypeObject本身是也一个PyVarObject
额,这个东西太复杂了,一堆堆的函数指针,看不懂。
创建与析构?
C API函数和这些函数指针的对应关系(调用关系):
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
所有的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扩展有该类型)。关于该类型的一个介绍见PEP353。
源码位于: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函数 | 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.htmlhttp://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
相关文章推荐
- Python源码学习-PyTypeObject
- Python源码学习之初始化(三)-PyDictObject的初始化
- 解决"学习python-flask教程,下载源码运行的时候出现:TypeError: 'bool' object is not callable 错误代码:"
- Python源码学习之初始化(三)-PyDictObject的初始化
- Python学习笔记:学习爬虫时遇到的问题TypeError: cannot use a string pattern on a bytes-like object 与解决办法
- Python源码学习七 .py文件的解释
- Python学习笔记 --- TypeError: 'unicode' object is not callable
- Python源码学习七 .py文件的解释
- Python源码剖析[12] —— 字典对象PyDictObject(1)
- Python源码剖析[13] —— 字典对象PyDictObject(2)
- TypeError: 'tuple' object is not callable 分类: python学习 2014-03-18 10:51 696人阅读 评论(0) 收藏
- Python源码分析-PyDictObject
- [Python源码学习]之Py_InitializeEx
- python3学习笔记1--TypeError: 'dict' object is not callable的解决
- Python学习笔记 --- 解析 type 和 object
- size_t PyObject PyVarObject PyTypeObject
- PyObject、PyVarObject和PyTypeObject
- python3.6 TypeError: 'dict_keys' object does not support indexing
- Python学习札记(三十) 面向对象编程 Object Oriented Program 1
- Python源码学习:Python函数浅析-无参函数