PyObjectにイテレータがあるかどうかをテストする方法


8

Pythonの拡張機能としてC関数を実装しています。の中では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がすべてのオブジェクトに対してゼロを返すのはなぜですか?

回答:


2

PyIter_Checkオブジェクトイテレータであるかどうかをチェックするためのものであり、イテレータを提供できるかどうかではありません。がないようPyIterable_Checkです。

さらに、PythonはEAFPをほぼ強制します。__iter__例外を発生させるものは何でも提供できるため、PyObject_GetIterとにかくエラーをチェックする必要があるため、*_Check関数の唯一のポイントは、早期の健全性チェックを提供することです(場合によっては、より優れたエラーメッセージが表示されます)。


ありがとうございました!超役立つ。例外処理について学習します :)
thehorseisbrown

@thehorseisbrown:Py_DECREF現存する所有参照の適切なsは別として、通常はとだけ言うことができますPyObject *const x=Py_Foo(…); if(!x) return 0;
Davis Herring
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.