用 tp_iternext 或 PyIter_Next 迭代差异

Difference iterating with tp_iternext or PyIter_Next

如果我编写一个 C 函数来处理可迭代对象,那么我会先创建一个迭代器,然后循环遍历它。

iterator = PyObject_GetIter(sequence);
if (iterator == NULL) {
    return NULL;
}
while (( item = PyIter_Next(iterator) )) {
    ...
}

这很好用,但我也看到一些函数使用 tp_iternext:

iterator = PyObject_GetIter(sequence); // ....

iternext = *Py_TYPE(iterator)->tp_iternext;
while (( item = iternext(iterator) )) {
    ...
}

第二种方法似乎更快(我只有一个数据点:我的 Windows 计算机和我的 msvc 编译器)。

iternext 方法更快是否只是巧合,这两者之间有什么显着差异吗?

python 文档的链接: PyIter_Next, tp_iternext 我已经阅读过它们,但对我来说不清楚何时以及为什么应该首选它们。

source code for PyIter_Next 显示它只是检索 tp_iternext 插槽并调用它 并清除可能发生或未发生的 StopIteration 异常.

如果您显式使用 tp_iternext,则在用尽迭代器时必须检查此 StopIteration


顺便说一下:tp_iternext 的文档还说:

iternextfunc PyTypeObject.tp_iternext

An optional pointer to a function that returns the next item in an iterator. When the iterator is exhausted, it must return NULL; a StopIteration exception may or may not be set. When another error occurs, it must return NULL too. Its presence signals that the instances of this type are iterators.

虽然 PyIter_Next 的文档中没有这样的提及。

所以 PyIter_Next 是简单 和安全 遍历迭代器的方法。你可以使用 tp_iternext 但你必须小心不要在最后触发 StopIteration 异常。