2012-03-26 1 views
2

PySequence_Lengthを使用して、CでPython辞書の長さを取得しようとしています。PyDict_Sizeを使用することができますが、もっと汎用的な関数特定の状況ではPython C-API:辞書で `PySequence_Length`を使用する

PyObject* d = PyDict_New(); 
Py_ssize_t res = PySequence_Length(d); 

printf("Result : %ld\n", res); 
if (res == -1) PyErr_Print(); 

これは失敗し、エラーを出力します。

TypeError: object of type 'dict' has no len()

私の質問は:なぜこれができませんの?

Py_ssize_t PySequence_Length(PyObject *o)

Returns the number of objects in sequence o on success, and -1 on failure. For objects that do not provide sequence protocol, this is equivalent to the Python expression len(o).

辞書タイプは__len__属性を持たないため、及び(dは辞書です)表現len(d)ので、きちんと返す:Python辞書オブジェクトはシーケンスのプロトコルをサポートしていませんが、PySequence_Lengthためdocumentation氏は述べていますPythonの長さでは、なぜPySequence_LengthがCで失敗するのか分かりません。

何か説明がありますか?ここに書類が間違っていますか?

答えて

4

文書は誤解を招く可能性があります。はい。 dictはシーケンスプロトコルのいくつかの部分を実装しているにもかかわらず、シーケンスではありません(シーケンスプロトコルの一部である包含テスト用)。Python/CタイプAPIのこのような区別は残念ですが、数十年前にデザインの選択をしました。ドキュメンテーションはその区別を反映していますが、同様に扱いにくいです。それは、Pythonクラスののです。これは、Pythonクラスのふちまいに関係なく、len(o)と同じことです。 C型の場合、型がsizefuncのシーケンス版を実装していない場合、PySequence_Length()は、型がsizefuncのマッピング版を持っているかどうかを考慮せずに例外を送出します。

シーケンスがあるかどうか完全にわからない場合は、代わりにPyObject_Size()を使用してください。実際、PySequence_Length()と呼ぶ理由はほとんどありません。通常はタイプを知っている(あなたが作成したばかりなので、型固有の長さ関数やマクロをPyList_GET_SIZE()のように呼ぶこともできます)、シーケンスであるかどうかも分かりません。