如何测试PyObject是否具有迭代器

9
我正在将一个C函数作为Python的扩展实现。在abstract.h中,我找到以下内容:
/* ==== Iterators ================================================ */

/* Takes an object and returns an iterator for it.
   This is typically a new iterator but if the argument is an iterator, this
   returns itself. */
PyAPI_FUNC(PyObject *) PyObject_GetIter(PyObject *);

/* Returns 1 if the object 'obj' provides iterator protocols, and 0 otherwise.

   This function always succeeds. */
PyAPI_FUNC(int) PyIter_Check(PyObject *);

当我尝试在明显不可迭代的对象(如数字)上使用PyObject_GetIter获取迭代器时,会出现错误SystemError: <built-in function xxx> returned a result with an error set

static PyObject *my_method(PyObject *self, PyObject *args) 
{
    PyObject *obj;
    PyArg_ParseTuple(args, "O", &obj)
    //  printf("\ncheck %d",PyIter_Check(obj)); // always 0
    PyObject *iter = PyObject_GetIter(obj); // throws error
    return PyLong_FromLong(0);
}

我希望自行处理错误。因此,我尝试使用PyIter_Check函数来测试对象是否具有迭代器。然而,无论我提供哪些对象,包括可迭代的对象,该函数都会返回0。
我认为这可能是由于PyAPI_FUNC()宏引起的,但我在pyport.h中找到了它,并且似乎只添加了__declspec
为什么PyIter_Check函数对所有对象都返回零呢?
1个回答

3

PyIter_Check 用于检查一个对象是否是迭代器,而不是检查它是否能够提供迭代器。看起来并没有 PyIterable_Check

此外,Python基本上强制执行 EAFP 原则:因为任何东西都可以提供一个引发异常的 __iter__,所以你必须检查从 PyObject_GetIter 返回的错误,因此 *_Check 函数的唯一目的是提供早期的健全性检查(有时带有更好的错误消息)。


谢谢!非常有帮助。我要学习异常处理:) - thehorseisbrown
除了对现有拥有的引用进行适当的Py_DECREF之外,通常您只需要这样说:PyObject *const x=Py_Foo(…); if(!x) return 0; - Davis Herring

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接