为什么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元素?
我不这么认为。有两个原因:
1)在Python源代码中,它只检查名称与NULL。
据我所知,PyMethodDef
数组用于两个地方:将方法附加到类型以及将方法附加到模块时。
要找到相关的代码位,首先注意到所有类型都经过PyType_Ready
,大多数模块都会通过PyModule_Init
,因此在那里开始搜索。 PyModule_Create
转发给PyModule_Create2
。 PyType_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自动零无论如何,哨兵。我不知道为什么这个公约似乎是要设定两个要素,但是按照惯例有些事情要说。
@Olaf为什么要删除C标签?这是我在这里调查的C代码。 – MSeifert
“_I我知道c需要一个标记来知道它何时需要”停止“_” - 这是错误的,没有语言的要求,也没有用于C中的大多数数组。“# – Olaf
”不,您正在调查一个错误的Python实现先决条件。 – Olaf