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

问题描述:

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

例如zip

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

为什么出现 “前哨阵” 中的最后PyMethodDef有两个NULL S'为什么不只是1?或者因为__reduce__有4个条目为什么不是4 NULL s作为sentinel元素?

+0

@Olaf为什么要删除C标签?这是我在这里调查的C代码。 – MSeifert

+0

“_I我知道c需要一个标记来知道它何时需要”停止“_” - 这是错误的,没有语言的要求,也没有用于C中的大多数数组。“# – Olaf

+0

”不,您正在调查一个错误的Python实现先决条件。 – Olaf

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

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

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

要找到相关的代码位,首先注意到所有类型都经过PyType_Ready,大多数模块都会通过PyModule_Init,因此在那里开始搜索。 PyModule_Create转发给PyModule_Create2PyType_Ready通过内部函数add_methods处理方法。在PyModule_Create2中,如果您想自己做低等级的东西,并且又调用内部函数_add_methods_to_object,则所有调用PyModule_AddFunctions实际上都是public function

这两个内部函数都有一个for循环来遍历方法并将它们添加到相关字典中。在bothcases继续循环的条件是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自动零无论如何,哨兵。我不知道为什么这个公约似乎是要设定两个要素,但是按照惯例有些事情要说。