Aufrufprotokoll¶
CPython unterstützt zwei verschiedene Aufrufprotokolle: tp_call und vectorcall.
Das tp_call Protokoll¶
Instanzen von Klassen, die tp_call setzen, sind aufrufbar. Die Signatur des Slots ist
PyObject *tp_call(PyObject *callable, PyObject *args, PyObject *kwargs);
Ein Aufruf erfolgt mit einem Tupel für die Positionsargumente und einem Dictionary für die Schlüsselwortargumente, ähnlich wie bei callable(*args, **kwargs) in Python-Code. args darf nicht NULL sein (verwenden Sie ein leeres Tupel, wenn keine Argumente vorhanden sind), aber kwargs darf NULL sein, wenn keine Schlüsselwortargumente vorhanden sind.
Diese Konvention wird nicht nur von tp_call verwendet: tp_new und tp_init übergeben Argumente ebenfalls auf diese Weise.
Um ein Objekt aufzurufen, verwenden Sie PyObject_Call() oder eine andere Aufruf-API.
Das Vectorcall-Protokoll¶
Hinzugefügt in Version 3.9.
Das Vectorcall-Protokoll wurde in PEP 590 als zusätzliches Protokoll zur effizienteren Gestaltung von Aufrufen eingeführt.
Als Faustregel wird CPython bei internen Aufrufen Vectorcall bevorzugen, wenn das aufrufbare Objekt dies unterstützt. Dies ist jedoch keine feste Regel. Zusätzlich verwenden einige Drittanbietererweiterungen tp_call direkt (anstatt PyObject_Call() zu verwenden). Daher muss eine Klasse, die Vectorcall unterstützt, auch tp_call implementieren. Darüber hinaus muss sich das aufrufbare Objekt unabhängig davon, welches Protokoll verwendet wird, gleich verhalten. Der empfohlene Weg, dies zu erreichen, ist das Setzen von tp_call auf PyVectorcall_Call(). Dies sollte wiederholt werden:
Warnung
Eine Klasse, die Vectorcall unterstützt, **muss** auch tp_call mit denselben Semantiken implementieren.
Geändert in Version 3.12: Das Flag Py_TPFLAGS_HAVE_VECTORCALL wird nun aus einer Klasse entfernt, wenn die Methode __call__() der Klasse neu zugewiesen wird. (Dies setzt intern nur tp_call und kann daher dazu führen, dass es sich anders verhält als die Vectorcall-Funktion.) In früheren Python-Versionen sollte Vectorcall nur mit unveränderlichen (immutable) oder statischen Typen verwendet werden.
Eine Klasse sollte Vectorcall nicht implementieren, wenn dies langsamer ist als tp_call. Wenn der Aufgerufene beispielsweise die Argumente sowieso in ein args-Tupel und ein kwargs-Dictionary konvertieren muss, dann hat die Implementierung von Vectorcall keinen Sinn.
Klassen können das Vectorcall-Protokoll implementieren, indem sie das Flag Py_TPFLAGS_HAVE_VECTORCALL aktivieren und tp_vectorcall_offset auf den Offset innerhalb der Objektstruktur setzen, an dem sich eine vectorcallfunc befindet. Dies ist ein Zeiger auf eine Funktion mit der folgenden Signatur
-
typedef PyObject *(*vectorcallfunc)(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)¶
- Teil der Stable ABI seit Version 3.12.
callable ist das aufgerufene Objekt.
- args ist ein C-Array, das die Positionsargumente gefolgt von den
Werten der Schlüsselwortargumente enthält. Dies kann NULL sein, wenn keine Argumente vorhanden sind.
- nargsf ist die Anzahl der Positionsargumente plus möglicherweise des
PY_VECTORCALL_ARGUMENTS_OFFSET-Flags. Um die tatsächliche Anzahl der Positionsargumente aus nargsf zu erhalten, verwenden SiePyVectorcall_NARGS().
- kwnames ist ein Tupel, das die Namen der Schlüsselwortargumente enthält;
mit anderen Worten, die Schlüssel des kwargs-Dictionarys. Diese Namen müssen Zeichenketten sein (Instanzen von
stroder einer Unterklasse) und sie müssen eindeutig sein. Wenn keine Schlüsselwortargumente vorhanden sind, kann kwnames stattdessen NULL sein.
-
PY_VECTORCALL_ARGUMENTS_OFFSET¶
- Teil der Stable ABI seit Version 3.12.
Wenn dieses Flag im nargsf-Argument eines Vectorcalls gesetzt ist, darf der Aufgerufene
args[-1]temporär ändern. Mit anderen Worten, args verweist auf das Argument 1 (nicht 0) im zugewiesenen Vektor. Der Aufgerufene muss den Wert vonargs[-1]vor der Rückgabe wiederherstellen.Für
PyObject_VectorcallMethod()bedeutet dieses Flag stattdessen, dassargs[0]geändert werden kann.Wo immer dies kostengünstig möglich ist (ohne zusätzliche Allokation), werden Aufrufer ermutigt,
PY_VECTORCALL_ARGUMENTS_OFFSETzu verwenden. Dies ermöglicht es Aufrufbaren wie gebundenen Methoden, ihre nachfolgenden Aufrufe (die ein vorangestelltes self-Argument enthalten) sehr effizient durchzuführen.Hinzugefügt in Version 3.8.
Um ein Objekt aufzurufen, das Vectorcall implementiert, verwenden Sie eine Aufruf-API-Funktion wie bei jedem anderen Aufrufbaren auch. PyObject_Vectorcall() wird normalerweise am effizientesten sein.
Rekursionskontrolle¶
Bei der Verwendung von tp_call müssen sich Aufgerufene nicht um Rekursion kümmern: CPython verwendet Py_EnterRecursiveCall() und Py_LeaveRecursiveCall() für Aufrufe, die mit tp_call erfolgen.
Aus Effizienzgründen ist dies bei Aufrufen mit Vectorcall nicht der Fall: Der Aufgerufene sollte bei Bedarf Py_EnterRecursiveCall und Py_LeaveRecursiveCall verwenden.
Vectorcall-Unterstützungs-API¶
-
Py_ssize_t PyVectorcall_NARGS(size_t nargsf)¶
- Teil der Stable ABI seit Version 3.12.
Gibt die tatsächliche Anzahl der Argumente zurück, basierend auf einem Vectorcall-Argument nargsf. Entspricht derzeit
(Py_ssize_t)(nargsf & ~PY_VECTORCALL_ARGUMENTS_OFFSET)
Die Funktion
PyVectorcall_NARGSsollte jedoch verwendet werden, um zukünftige Erweiterungen zu ermöglichen.Hinzugefügt in Version 3.8.
-
vectorcallfunc PyVectorcall_Function(PyObject *op)¶
Wenn op das Vectorcall-Protokoll nicht unterstützt (entweder weil der Typ es nicht tut oder weil die spezifische Instanz es nicht tut), gibt diese Funktion NULL zurück. Andernfalls gibt sie den im op gespeicherten Vectorcall-Funktionszeiger zurück. Diese Funktion löst nie eine Ausnahme aus.
Dies ist hauptsächlich nützlich, um zu überprüfen, ob op Vectorcall unterstützt oder nicht, was durch die Überprüfung von
PyVectorcall_Function(op) != NULLerfolgen kann.Hinzugefügt in Version 3.9.
-
PyObject *PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict)¶
- Teil der Stable ABI seit Version 3.12.
Ruft die
vectorcallfuncvon callable mit Positions- und Schlüsselwortargumenten auf, die jeweils in einem Tupel und einem Dictionary übergeben werden.Dies ist eine spezialisierte Funktion, die für den
tp_call-Slot vorgesehen ist oder in einer Implementierung vontp_callverwendet wird. Sie prüft nicht das FlagPy_TPFLAGS_HAVE_VECTORCALLund greift nicht auftp_callzurück.Hinzugefügt in Version 3.8.
Objekt-Aufruf-API¶
Für den Aufruf eines Python-Objekts stehen verschiedene Funktionen zur Verfügung. Jede konvertiert ihre Argumente in eine Konvention, die vom aufgerufenen Objekt unterstützt wird – entweder tp_call oder vectorcall. Um möglichst wenig Konvertierungsaufwand zu betreiben, wählen Sie die Funktion, die am besten zum Format Ihrer verfügbaren Daten passt.
Die folgende Tabelle fasst die verfügbaren Funktionen zusammen; Details finden Sie in der jeweiligen Dokumentation.
Funktion |
callable |
args |
kwargs |
|---|---|---|---|
|
tuple |
dict/ |
|
|
— |
— |
|
|
1 Objekt |
— |
|
|
tuple/ |
— |
|
|
format |
— |
|
obj + |
format |
— |
|
|
variadisch |
— |
|
obj + Name |
variadisch |
— |
|
obj + Name |
— |
— |
|
obj + Name |
1 Objekt |
— |
|
|
vectorcall |
vectorcall |
|
|
vectorcall |
dict/ |
|
arg + Name |
vectorcall |
vectorcall |
-
PyObject *PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)¶
- Rückgabewert: Neue Referenz. Teil der Stabilen ABI.
Ruft ein aufrufbares Python-Objekt callable mit den im Tupel args angegebenen Argumenten und den im Dictionary kwargs angegebenen benannten Argumenten auf.
args darf nicht NULL sein; verwenden Sie ein leeres Tupel, wenn keine Argumente benötigt werden. Wenn keine benannten Argumente benötigt werden, kann kwargs NULL sein.
Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
Dies entspricht dem Python-Ausdruck:
callable(*args, **kwargs).
-
PyObject *PyObject_CallNoArgs(PyObject *callable)¶
- Rückgabewert: Neue Referenz. Teil der Stable ABI seit Version 3.10.
Ruft ein aufrufbares Python-Objekt callable ohne Argumente auf. Es ist der effizienteste Weg, ein aufrufbares Python-Objekt ohne Argumente aufzurufen.
Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
Hinzugefügt in Version 3.9.
-
PyObject *PyObject_CallOneArg(PyObject *callable, PyObject *arg)¶
- Rückgabewert: Neue Referenz.
Ruft ein aufrufbares Python-Objekt callable mit genau 1 Positionsargument arg und ohne Schlüsselwortargumente auf.
Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
Hinzugefügt in Version 3.9.
-
PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)¶
- Rückgabewert: Neue Referenz. Teil der Stabilen ABI.
Ruft ein aufrufbares Python-Objekt callable mit den im Tupel args angegebenen Argumenten auf. Wenn keine Argumente benötigt werden, kann args NULL sein.
Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
Dies entspricht dem Python-Ausdruck:
callable(*args).
-
PyObject *PyObject_CallFunction(PyObject *callable, const char *format, ...)¶
- Rückgabewert: Neue Referenz. Teil der Stabilen ABI.
Ruft ein aufrufbares Python-Objekt callable mit einer variablen Anzahl von C-Argumenten auf. Die C-Argumente werden mithilfe einer Formatzeichenkette im Stil von
Py_BuildValue()beschrieben. Das Format kann NULL sein, was bedeutet, dass keine Argumente übergeben werden.Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
Dies entspricht dem Python-Ausdruck:
callable(*args).Beachten Sie, dass
PyObject_CallFunctionObjArgs()eine schnellere Alternative ist, wenn Sie nur PyObject* Argumente übergeben.Geändert in Version 3.4: Der Typ von format wurde von
char *geändert.
-
PyObject *PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)¶
- Rückgabewert: Neue Referenz. Teil der Stabilen ABI.
Ruft die Methode mit dem Namen name des Objekts obj mit einer variablen Anzahl von C-Argumenten auf. Die C-Argumente werden durch eine Formatzeichenkette im Stil von
Py_BuildValue()beschrieben, die ein Tupel erzeugen sollte.Das Format kann NULL sein, was bedeutet, dass keine Argumente übergeben werden.
Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
Dies entspricht dem Python-Ausdruck:
obj.name(arg1, arg2, ...).Beachten Sie, dass
PyObject_CallMethodObjArgs()eine schnellere Alternative ist, wenn Sie nur PyObject* Argumente übergeben.Geändert in Version 3.4: Die Typen von name und format wurden von
char *geändert.
-
PyObject *PyObject_CallFunctionObjArgs(PyObject *callable, ...)¶
- Rückgabewert: Neue Referenz. Teil der Stabilen ABI.
Ruft ein aufrufbares Python-Objekt callable mit einer variablen Anzahl von PyObject* Argumenten auf. Die Argumente werden als variable Anzahl von Parametern gefolgt von NULL übergeben.
Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
Dies entspricht dem Python-Ausdruck:
callable(arg1, arg2, ...).
-
PyObject *PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...)¶
- Rückgabewert: Neue Referenz. Teil der Stabilen ABI.
Ruft eine Methode des Python-Objekts obj auf, wobei der Name der Methode als Python-Zeichenkettenobjekt in name angegeben wird. Sie wird mit einer variablen Anzahl von PyObject* Argumenten aufgerufen. Die Argumente werden als variable Anzahl von Parametern gefolgt von NULL übergeben.
Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
-
PyObject *PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name)¶
Ruft eine Methode des Python-Objekts obj ohne Argumente auf, wobei der Name der Methode als Python-Zeichenkettenobjekt in name angegeben wird.
Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
Hinzugefügt in Version 3.9.
-
PyObject *PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg)¶
Ruft eine Methode des Python-Objekts obj mit einem einzelnen Positionsargument arg auf, wobei der Name der Methode als Python-Zeichenkettenobjekt in name angegeben wird.
Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
Hinzugefügt in Version 3.9.
-
PyObject *PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)¶
- Teil der Stable ABI seit Version 3.12.
Ruft ein aufrufbares Python-Objekt callable auf. Die Argumente sind dieselben wie für
vectorcallfunc. Wenn callable vectorcall unterstützt, ruft dies direkt die im callable gespeicherte Vectorcall-Funktion auf.Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
Hinzugefügt in Version 3.9.
-
PyObject *PyObject_VectorcallDict(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwdict)¶
Ruft callable mit Positionsargumenten auf, die genau wie im vectorcall-Protokoll übergeben werden, jedoch mit Schlüsselwortargumenten, die als Dictionary kwdict übergeben werden. Das args-Array enthält nur die Positionsargumente.
Unabhängig davon, welches Protokoll intern verwendet wird, ist eine Konvertierung der Argumente erforderlich. Daher sollte diese Funktion nur verwendet werden, wenn der Aufrufer bereits ein Dictionary für die Schlüsselwortargumente bereithält, aber kein Tupel für die Positionsargumente.
Hinzugefügt in Version 3.9.
-
PyObject *PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames)¶
- Teil der Stable ABI seit Version 3.12.
Ruft eine Methode unter Verwendung der vectorcall-Aufrufkonvention auf. Der Name der Methode wird als Python-String name übergeben. Das Objekt, dessen Methode aufgerufen wird, ist args[0], und das Array args ab args[1] stellt die Argumente des Aufrufs dar. Es muss mindestens ein Positionsargument vorhanden sein. nargsf ist die Anzahl der Positionsargumente einschließlich args[0], zuzüglich
PY_VECTORCALL_ARGUMENTS_OFFSET, wenn der Wert vonargs[0]vorübergehend geändert werden darf. Schlüsselwortargumente können genauso übergeben werden wie inPyObject_Vectorcall().Wenn das Objekt das Merkmal
Py_TPFLAGS_METHOD_DESCRIPTORbesitzt, wird die ungebundene Methodendeskriptor mit dem gesamten args-Vektor als Argumente aufgerufen.Gibt das Ergebnis des Aufrufs im Erfolgsfall zurück oder löst eine Ausnahme aus und gibt NULL im Fehlerfall zurück.
Hinzugefügt in Version 3.9.
Call Support API¶
-
int PyCallable_Check(PyObject *o)¶
- Teil der Stable ABI.
Bestimmt, ob das Objekt o aufrufbar ist. Gibt
1zurück, wenn das Objekt aufrufbar ist, und0andernfalls. Diese Funktion ist immer erfolgreich.