Python源码学习之PyObject和PyTypeObject
什么是PyObject和PyTypeObject?
在Python中,每一个对象都是一个PyObject结构体的实例,该结构体包含对象的类型信息和对象的值。
而每一种对象类型都对应了一个PyTypeObject结构体,PyTypeObject定义了该类型的具体属性、操作以及特定类型的save-restore函数等。
如何学习PyObject和PyTypeObject?
学习PyObject和PyTypeObject的方法及步骤如下:
1. 确定学习版本
最好先确定要学习的Python源码版本,以便对应版本的源码操作和习惯,这里以Python 3.9.6版本为例。
2. 下载源码
从官方网站https://www.python.org/downloads/下载对应版本的Python源码。
3. 了解源码目录结构
在下载并解压源码后,需要了解Python源码的目录结构以及各目录含义。
主要涉及的目录及其含义如下:
- Include: 存储Python的头文件,用于C扩展程序的构建。
- Lib: 存储Python标准库的源码。
- Modules: 存储Python的扩展模块源码。
- Objects: 存储Python对象的类型实现以及其他对象。
4. 学习PyObject和PyTypeObject的定义和结构
了解PyObject和PyTypeObject的定义和结构非常简单,只需要在Objects目录下找到对应的源文件,阅读其中的相关代码即可。
5. 学习PyObject和PyTypeObject的相关函数
在PyTypeObject中,有很多操作函数(比如__new__、init、tp_alloc等),需要逐一了解其作用和实现。
同时,对于一些特殊的类型(如元组、字典、列表等),需要特别关注其PyTypeObject的实现和相关函数的实现。
6.试着实现一个小例子
Python源码的学习,尤其是对于初学者来说,往往具有较高的难度和复杂度。因此在学习的同时,可以边阅读源码,边实现一些小的示例代码,以便更加深入地理解源码。
例如,可以实现一个自定义类型,然后对该类型的PyTypeObject进行相关操作,来更好地理解PyObject和PyTypeObject的功能和作用。
示例说明
以下为两个示例代码,用于展示如何通过PyObject和PyTypeObject实现自定义类型的操作。
1. 创建自定义类型
#include <Python.h>
/* 定义自定义类型 */
typedef struct {
PyObject_HEAD // PyObjec_HEAD将用户定义类型对象和Python内部对象进行关联
PyObject* first;
PyObject* second;
} custom_type;
/* new方法 */
static PyObject* custom_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
{
custom_type* self;
self = (custom_type*)type->tp_alloc(type, 0);
return (PyObject*)self;
}
/* init方法 */
static int custom_init(custom_type* self, PyObject* args, PyObject* kwds)
{
/* 解析参数 */
if (!PyArg_ParseTuple(args, "OO", &(self->first), &(self->second))) {
return -1;
}
return 0;
}
/* dealloc方法 */
static void custom_dealloc(custom_type* self)
{
Py_XDECREF(self->first);
Py_XDECREF(self->second);
Py_TYPE(self)->tp_free((PyObject*)self);
}
/* 定义自定义类型的方法和属性 */
static PyMethodDef custom_methods[] = {
{ NULL, NULL, 0, NULL }
};
static PyMemberDef custom_members[] = {
{ "first", T_OBJECT_EX, offsetof(custom_type, first), 0, "Custom object first" },
{ "second", T_OBJECT_EX, offsetof(custom_type, second), 0, "Custom object second" },
{ NULL }
};
/* 定义自定义类型对象 */
static PyTypeObject custom_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"customtype", /* tp_name */
sizeof(custom_type), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)custom_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE, /* tp_flags */
"custom type", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
custom_methods, /* tp_methods */
custom_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)custom_init, /* tp_init */
0, /* tp_alloc */
custom_new, /* tp_new */
};
/* 模块初始化 */
static struct PyModuleDef custom_module = {
PyModuleDef_HEAD_INIT,
"custom", /* module name */
"This is a custom module", /* docstring */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
NULL, NULL, NULL, NULL, NULL
};
PyMODINIT_FUNC PyInit_custom(void)
{
PyObject* m;
if (PyType_Ready(&custom_Type) < 0) {
return NULL;
}
m = PyModule_Create(&custom_module);
if (m == NULL) {
return NULL;
}
Py_INCREF(&custom_Type);
PyModule_AddObject(m, "custom", (PyObject*)&custom_Type);
return m;
}
以上代码创建了一个自定义类型custom_type,并定义了其PyTypeObject和相关函数。
2. 调用自定义类型
import custom
# 实例化自定义类型
obj = custom.custom()
# 设置自定义类型的属性
obj.first = 123
obj.second = "hello"
# 打印自定义类型的属性
print(obj.first)
print(obj.second)
以上代码调用了自定义类型custom_type并对其属性进行操作。此时运行上述代码,输出结果为:
123
hello
以上两个示例代码展示了如何通过Python的PyTypeObject和相关函数实现自定义类型,以及如何在Python中实例化该自定义类型并对其属性进行操作。在学习过程中,可以根据需求和进展实现更多的示例,以便更好地理解Python源码中的相关机制。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python源码学习之PyObject和PyTypeObject - Python技术站