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 Sie PyVectorcall_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 str oder 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 von args[-1] vor der Rückgabe wiederherstellen.

Für PyObject_VectorcallMethod() bedeutet dieses Flag stattdessen, dass args[0] geändert werden kann.

Wo immer dies kostengünstig möglich ist (ohne zusätzliche Allokation), werden Aufrufer ermutigt, PY_VECTORCALL_ARGUMENTS_OFFSET zu 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_NARGS sollte 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) != NULL erfolgen 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 vectorcallfunc von 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 von tp_call verwendet wird. Sie prüft nicht das Flag Py_TPFLAGS_HAVE_VECTORCALL und greift nicht auf tp_call zurü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

PyObject_Call()

PyObject *

tuple

dict/NULL

PyObject_CallNoArgs()

PyObject *

PyObject_CallOneArg()

PyObject *

1 Objekt

PyObject_CallObject()

PyObject *

tuple/NULL

PyObject_CallFunction()

PyObject *

format

PyObject_CallMethod()

obj + char*

format

PyObject_CallFunctionObjArgs()

PyObject *

variadisch

PyObject_CallMethodObjArgs()

obj + Name

variadisch

PyObject_CallMethodNoArgs()

obj + Name

PyObject_CallMethodOneArg()

obj + Name

1 Objekt

PyObject_Vectorcall()

PyObject *

vectorcall

vectorcall

PyObject_VectorcallDict()

PyObject *

vectorcall

dict/NULL

PyObject_VectorcallMethod()

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 von args[0] vorübergehend geändert werden darf. Schlüsselwortargumente können genauso übergeben werden wie in PyObject_Vectorcall().

Wenn das Objekt das Merkmal Py_TPFLAGS_METHOD_DESCRIPTOR besitzt, 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 1 zurück, wenn das Objekt aufrufbar ist, und 0 andernfalls. Diese Funktion ist immer erfolgreich.