python定义float类型数组_Python(61)扩展和嵌入2.自定义扩展类型2.1.基础

友情提示:此为高阶主题,初级码农请绕行。

2. 自定义扩展类型:教程

Python 允许编写 C 扩展模块定义可以从 Python 代码中操纵的新类型,这很像内置的  str 和  list 类型。所有扩展类型的代码都遵循一个模式,但是在您开始之前,您需要了解一些细节。这份文件是对这个主题介绍。

2.1. 基础

CPython 运行时将所有 Python 对象都视为类型  PyObject* 的变量,即所有 Python 对象的"基础类型"。  PyObject 结构体本身包含了对象的 reference count 和对象的"类型对象"。类型对象确定解释器需要调用哪些 (C) 函数,例如一个属性查询一个对象,一个方法调用,或者与另一个对象相乘。这些 C 函数被称为“类型方法”。所以,如果你想要定义新的扩展类型,需要创建新的类型对象。这类事情只能用例子解释,这里用一个最小化但完整的的模块,定义了新的类型叫做  Custom 在C扩展模块  custom 里。注解 这里展示的方法是定义  static 扩展类型的传统方法。可以适合大部分用途。C API也可以定义在堆上分配的扩展类型,使用  PyType_FromSpec() 函数,但不在本入门里讨论。
#define PY_SSIZE_T_CLEAN#include typedef struct {
PyObject_HEAD/* Type-specific fields go here. */
} CustomObject;static PyTypeObject CustomType = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "custom.Custom",
.tp_doc = "Custom objects",
.tp_basicsize = sizeof(CustomObject),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_new = PyType_GenericNew,
};static PyModuleDef custommodule = {
PyModuleDef_HEAD_INIT,
.m_name = "custom",
.m_doc = "Example module that creates an extension type.",
.m_size = -1,
};
PyMODINIT_FUNCPyInit_custom(void)
{
PyObject *m;if (PyType_Ready(&CustomType) < 0)return NULL;
m = PyModule_Create(&custommodule);if (m == NULL)return NULL;
Py_INCREF(&CustomType);if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
Py_DECREF(&CustomType);
Py_DECREF(m);return NULL;
}return m;
}
这部分很容易理解,这是为了跟上一章能对接上。这个文件定义了三件事:
  1. Custom 类的对象 object 包含了: CustomObject 结构,这会为每个 Custom 实例分配一次。
  2. Custom type 的行为:这是 CustomType 结构体,其定义了一堆标识和函数指针,会指向解释器里请求的操作。
  3. 初始化 custom 模块: PyInit_custom 函数和对应的 custommodule 结构体。
结构的第一块是
typedef struct {
PyObject_HEAD
} CustomObject;
这就是一个自定义对象所包含的。  PyObject_HEAD 是强制要求必须在每个对象结构体之前,用以定义一个类型为  PyObject 的字段叫  ob_base ,包含了一个指针指向类型对象和一个引用计数(这可以用宏  Py_REFCNT 和  Py_TYPE 来区分)。用宏来抽象,使得附加字段可以用调试构建。注解 注意在宏  PyObject_HEAD 后没有分号。意外添加分号会导致编译器提示出错。当然,对象除了在  PyObject_HEAD 存储数据外,还有额外数据;例如,如下定义了标准的Python浮点数:
typedef struct {
PyObject_HEADdouble ob_fval;
} PyFloatObject;
第二个位是类型对象的定义:
static PyTypeObject CustomType = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "custom.Custom",
.tp_doc = "Custom objects",
.tp_basicsize = sizeof(CustomObject),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_new = PyType_GenericNew,
};
 推荐使用如上C99风格的初始化,以避免列出所有的  PyTypeObject 字段,其中很多是你不需要关心的,这样也可以避免关注字段的定义顺序。在  object.h 中实际定义的  PyTypeObject 具有比如上定义更多的 字段。剩余的字段会由 C 编译器用零来填充,通常的做法是不显式地指定它们,除非你确实需要它们。我们先挑选一部分,每次一个字段:
PyVarObject_HEAD_INIT(NULL, 0)
这一行是强制的样板,用以初始化如上提到的  ob_base 字段:
.tp_name = "custom.Custom",
我们的类型的名称。这将出现在我们的对象的默认文本表示形式和某些错误消息中,例如:>>>
>>> "" + custom.Custom()Traceback (most recent call last):
File "", line 1, in TypeError: can only concatenate str (not "custom.Custom") to str
Note that the name is a dotted name that includes both the module name and the name of the type within the module. The module in this case is  custom and the type is  Custom, so we set the type name to  custom.Custom. Using the real dotted import path is important to make your type compatible with the  pydoc and  pickle modules.
.tp_basicsize = sizeof(CustomObject),
.tp_itemsize = 0,
This is so that Python knows how much memory to allocate when creating new  Custom instances.  tp_itemsize is only used for variable-sized objects and should otherwise be zero. If you want your type to be subclassable from Python, and your type has the same  tp_basicsize as its base type, you may have problems with multiple inheritance. A Python subclass of your type will have to list your type first in its  __bases__, or else it will not be able to call your type's  __new__() method without getting an error. You can avoid this problem by ensuring that your type has a larger value for  tp_basicsize than its base type does. Most of the time, this will be true anyway, because either your base type will be  object, or else you will be adding data members to your base type, and therefore increasing its size.We set the class flags to  Py_TPFLAGS_DEFAULT.
.tp_flags = Py_TPFLAGS_DEFAULT,
All types should include this constant in their flags. It enables all of the members defined until at least Python 3.3. If you need further members, you will need to OR the corresponding flags.We provide a doc string for the type in  tp_doc.
.tp_doc = "Custom objects",
To enable object creation, we have to provide a  tp_new handler. This is the equivalent of the Python method  __new__(), but has to be specified explicitly. In this case, we can just use the default implementation provided by the API function  PyType_GenericNew().
.tp_new = PyType_GenericNew,
Everything else in the file should be familiar, except for some code in  PyInit_custom():
if (PyType_Ready(&CustomType) < 0)return;
This initializes the  Custom type, filling in a number of members to the appropriate default values, including  ob_type that we initially set to  NULL.
Py_INCREF(&CustomType);if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
Py_DECREF(&CustomType);
Py_DECREF(m);return NULL;
}
This adds the type to the module dictionary. This allows us to create  Custom instances by calling the  Custom class:>>>
>>> import custom>>> mycustom = custom.Custom()
That's it! All that remains is to build it; put the above code in a file called  custom.c and:
from distutils.core import setup, Extension
setup(name="custom", version="1.0",
ext_modules=[Extension("custom", ["custom.c"])])
in a file called  setup.py; then typing
$ python setup.py build
at a shell should produce a file  custom.so in a subdirectory; move to that directory and fire up Python --- you should be able to  import custom and play around with Custom objects.That wasn't so hard, was it?Of course, the current Custom type is pretty uninteresting. It has no data and doesn't do anything. It can't even be subclassed.注解 While this documentation showcases the standard  distutils module for building C extensions, it is recommended in real-world use cases to use the newer and better-maintained  setuptools library. Documentation on how to do this is out of scope for this document and can be found in the Python Packaging User's Guide.

python定义float类型数组_Python(61)扩展和嵌入2.自定义扩展类型2.1.基础_第1张图片

你可能感兴趣的:(python定义float类型数组_Python(61)扩展和嵌入2.自定义扩展类型2.1.基础)