2017-04-12 2 views
1

Mehrere Python-Strukturen scheinen einen Sentinel zu benötigen (wahrscheinlich um zu wissen, wann "zu stoppen" ist). Aber warum haben einige, wie Arrays von PyMethodDef, ein Sentinel-Element mit mehreren NULL s initialisiert?Warum erfordern PyMethodDef-Arrays ein Sentinel-Element, das mehrere NULL enthält?

Zum Beispiel zip:

static PyMethodDef zip_methods[] = { 
    {"__reduce__", (PyCFunction)zip_reduce, METH_NOARGS, reduce_doc}, 
    {NULL,   NULL}   /* sentinel */ 
}; 

Warum die letzten PyMethodDef in dem "Sentinel-Array" hat die beide NULL s? Warum nicht nur 1? Oder vorausgesetzt, dass __reduce__ 4 Einträge hat, warum nicht 4 NULL s als Sentinel-Element?

+0

@Olaf Warum das C-Tag entfernen? Es ist C-Code, den ich hier untersuche. – MSeifert

+0

"_Ich erkenne, dass c einen Sentinel benötigt, um zu wissen, wann es" stoppen "_" - Das ist falsch und keine Anforderung der Sprache, noch für die meisten Arrays in C. – Olaf

+0

Nein, Sie untersuchen eine Python-Implementierung mit einem falschen Voraussetzung. – Olaf

Antwort

3

Ich glaube nicht, dass es tut. Aus zwei Gründen:

1) Im Python-Quellcode wird nur der Name mit NULL überprüft.

Soweit ich weiß, PyMethodDef Arrays werden an zwei Orten verwendet: beim Anfügen von Methoden an einen Typ und beim Anfügen von Methoden an ein Modul.

Um das relevante Bit des Codes zu finden, fangen Sie an zu notieren, dass alle Typen durch PyType_Ready gehen und die meisten Module durch PyModule_Init gehen, also starten Sie die Suche dort. PyModule_Create weiterleiten an PyModule_Create2. In PyType_Ready werden die Methoden von der internen Funktion add_methods behandelt. In PyModule_Create2 gibt es alle Anruf PyModule_AddFunctions, die eigentlich eine public function ist, wenn Sie Low-Level-Zeug selbst tun wollen und die wiederum die interne Funktion _add_methods_to_object aufruft.

Diese beiden internen Funktionen haben eine for-Schleife, um die Methoden zu durchlaufen und sie dem entsprechenden Wörterbuch hinzuzufügen. In bothcases ist die Bedingung zum Fortsetzen der Schleife meth->ml_name!=NULL.

Daher wird derzeit zumindest nur der Name überprüft.

2) In both C and C++ partial initialization guarantees that the remaining fields are zero/default initialized. Wenn Sie also das erste Element des Sentinels auf 0 initialisieren, wird sichergestellt, dass alle anderen Elemente auf 0 initialisiert werden. Sie können auch einfach {} verwenden.

(Als Randbemerkung, Python verwendet diese automatische Null Initialisierung viel mit dem großen structs es definiert, zum Beispiel PyTypeObject, die riesig ist und die man nur selten die Mühe Füllung vollständig in.)

Nach dieser Antwort schreiben I festgestellt, dass dies already been discussed hatte.


Also zusammenfassend - Python prüft nur die ml_name (obwohl das eine Implementierung Detail ist, damit ich in Zukunft ändern erraten können, wenn sie eine Verwendung für einen NULL Namen mit einer nicht NULL Methode zu finden) und C automatisch Nullen der Wächter sowieso. Ich weiß nicht, warum die Konvention scheint, zwei Elemente zu setzen, aber es gibt etwas, das von der folgenden Konvention zu sagen ist.

Verwandte Themen