python - 为什么 PyMethodDef 数组需要一个包含多个 NULL 的标记元素?

标签 python python-c-api

几个 Python 结构似乎需要一个哨兵(可能是为了知道什么时候“停止”)。但为什么有些元素(如 PyMethodDef 数组)有一个用多个 NULL 初始化的标记元素?

例如zip :

static PyMethodDef zip_methods[] = {
    {"__reduce__",   (PyCFunction)zip_reduce,   METH_NOARGS, reduce_doc},
    {NULL,           NULL}           /* sentinel */
};

为什么“哨兵数组”中的最后一个 PyMethodDef 有两个 NULL?为什么不只是 1?或者假设 __reduce__ 有 4 个条目,为什么不将 4 个 NULL 作为标记元素?

最佳答案

我不这么认为。有两个原因:

1) 在 Python 源代码中,它只检查名称是否为 NULL。

据我所知,PyMethodDef 数组用在两个地方:将方法附加到类型时,以及将方法附加到模块时。

要找到相关的代码位,首先要注意所有类型都经过 PyType_Ready,并且大多数模块都经过 PyModule_Init,因此从那里开始搜索。 PyModule_Create 转发到 PyModule_Create2。在 PyType_Ready 中,方法由内部函数处理 add_methods .在 PyModule_Create2 中,所有调用都是 PyModule_AddFunctions这实际上是一个 public function如果您想自己做低级的事情,然后调用内部函数 _add_methods_to_object

这两个内部函数都有一个 for 循环来遍历方法并将它们添加到相关字典中。在 both cases继续循环的条件是meth->ml_name!=NULL

因此,至少目前,只检查名称。

2) In both C and C++ partial initialization guarantees that the remaining fields are zero/default initialized .因此,只需将哨兵的第一个元素初始化为 0 即可确保所有其他元素都初始化为 0。您甚至可以只使用 {}

(附带说明,Python 大量使用这种自动零初始化及其定义的大型结构,例如 PyTypeObject,它很大,您很少费心去完整填写。)

写完这个答案后我发现这个有already been discussed .


所以总而言之——Python 只检查 ml_name(尽管这是一个实现细节,所以我想如果他们发现使用 NULL 名称和非NULL 方法),并且 C 无论如何都会自动将哨兵清零。我不知道为什么惯例似乎是设置两个元素,但遵循惯例还是有话要说的。

关于python - 为什么 PyMethodDef 数组需要一个包含多个 NULL 的标记元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43371780/

相关文章:

java - 最喜欢的开源 Google App Engine 应用(Java 或 Python)

python-3.x - python c-api : create bytes using existing buffer without copying

python - PyArg_ParseTupleAndKeywords() 中无值 PyObject 为 NULL

python - 从 Django 2.0 中的 LiveServerTestCase 获取正确的端口号

python - 什么 Python 库可以帮助可视化/渲染 4d(坐标+位置)矩阵?

Python Pandas 导出数据

Python,当键是科学格式的 float 时,如何按键对字典进行排序?

python - 分配到项目大小 > 1 的 Python 3.x 缓冲区

python - 将 Python 结构解析为 PyObject

python - 为什么 NumPy-C api 不警告我分配失败?