2012-03-26 9 views
2

Ich versuche PySequence_Length zu verwenden, um die Länge eines Python-Wörterbuchs in C zu bekommen. Ich weiß, dass ich PyDict_Size verwenden kann, aber ich bin daran interessiert, eine allgemeinere Funktion zu verwenden in bestimmten Kontexten.Python C-API: `PySequence_Length` mit Wörterbüchern verwenden

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

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

Dies schlägt fehl, und druckt den Fehler:

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

Meine Frage ist: Warum funktioniert das nicht? Obwohl Python-Dictionary-Objekte Sequenzprotokoll nicht unterstützen, die documentation für PySequence_Length sagt:

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).

Da ein Wörterbuchtyp ein __len__ Attribut hat, und da der Ausdruck len(d) (wo d ein Wörterbuch ist) richtig kehrt die Länge in Python, ich verstehe nicht, warum PySequence_Length in C ausfallen sollte.

Eine Erklärung? Ist die Dokumentation hier falsch?

Antwort

4

Die Dokumentation ist irreführend, ja. Ein dict ist keine Sequenz, obwohl es einige Teile des Sequenzprotokolls implementiert (für Eindämmtests, die Teil des Sequenzprotokolls sind). Diese besondere Unterscheidung in der API von Python/C-Typen ist bedauerlich, aber es ist ein Artefakt von eine Designentscheidung, die vor Jahrzehnten getroffen wurde. Die Dokumentation spiegelt diese Unterscheidung wider, wenn auch auf eine ebenso peinliche Weise. Was es zu sagen versucht ist, dass für Python-Klassen es ist die gleiche Sache wie len(o), unabhängig davon, was die Python-Klasse vorgibt zu sein. Wenn der Typ für C-Typen die Sequenzversion von sizefunc nicht implementiert, löst PySequence_Length() eine Ausnahme aus, ohne zu berücksichtigen, ob der Typ die Mappingversion von sizefunc hat.

Wenn Sie nicht ganz sicher sind, ob Sie eine Sequenz haben oder nicht, sollten Sie statt dessen 10 verwenden. In der Tat gibt es sehr wenig Grund zu rufen PySequence_Length(); normalerweise kennen Sie den Typ (weil Sie ihn gerade erstellt haben, und Sie können eine typspezifische Längenfunktion oder ein Makro wie PyList_GET_SIZE() aufrufen) oder Sie wissen nicht einmal, ob es sich um eine Sequenz handelt.

Verwandte Themen