Typobjektstrukturen

Vielleicht eine der wichtigsten Strukturen des Python-Objektsystems ist die Struktur, die einen neuen Typ definiert: die PyTypeObject-Struktur. Typobjekte können mit einer der PyObject_*- oder PyType_*-Funktionen behandelt werden, bieten aber für die meisten Python-Anwendungen nicht viel Interessantes. Diese Objekte sind grundlegend dafür, wie sich Objekte verhalten, und sind daher für den Interpreter selbst und für jedes Erweiterungsmodul, das neue Typen implementiert, sehr wichtig.

Typobjekte sind im Vergleich zu den meisten Standardtypen ziemlich groß. Der Grund für die Größe ist, dass jedes Typobjekt eine große Anzahl von Werten speichert, meist C-Funktionszeiger, von denen jeder einen kleinen Teil der Funktionalität des Typs implementiert. Die Felder des Typobjekts werden in diesem Abschnitt im Detail beschrieben. Die Felder werden in der Reihenfolge beschrieben, in der sie in der Struktur auftreten.

Zusätzlich zur folgenden Kurzübersicht bietet der Abschnitt Beispiele einen schnellen Einblick in die Bedeutung und Verwendung von PyTypeObject.

Kurzübersicht

„tp slots“

PyTypeObject Slot [1]

Typ

spezielle Methoden/Attribute

Info [2]

O

T

D

I

<R> tp_name

const char *

__name__

X

X

tp_basicsize

Py_ssize_t

X

X

X

tp_itemsize

Py_ssize_t

X

X

tp_dealloc

Destruktor

X

X

X

tp_vectorcall_offset

Py_ssize_t

X

X

(tp_getattr)

getattrfunc

__getattribute__, __getattr__

G

(tp_setattr)

setattrfunc

__setattr__, __delattr__

G

tp_as_async

PyAsyncMethods *

Sub-Slots

%

tp_repr

reprfunc

__repr__

X

X

X

tp_as_number

PyNumberMethods *

Sub-Slots

%

tp_as_sequence

PySequenceMethods *

Sub-Slots

%

tp_as_mapping

PyMappingMethods *

Sub-Slots

%

tp_hash

hashfunc

__hash__

X

G

tp_call

ternaryfunc

__call__

X

X

tp_str

reprfunc

__str__

X

X

tp_getattro

getattrofunc

__getattribute__, __getattr__

X

X

G

tp_setattro

setattrofunc

__setattr__, __delattr__

X

X

G

tp_as_buffer

PyBufferProcs *

Sub-Slots

%

tp_flags

unsigned long

X

X

?

tp_doc

const char *

__doc__

X

X

tp_traverse

traverseproc

X

G

tp_clear

inquiry

X

G

tp_richcompare

richcmpfunc

__lt__, __le__, __eq__, __ne__, __gt__, __ge__

X

G

(tp_weaklistoffset)

Py_ssize_t

X

?

tp_iter

getiterfunc

__iter__

X

tp_iternext

iternextfunc

__next__

X

tp_methods

PyMethodDef []

X

X

tp_members

PyMemberDef []

X

tp_getset

PyGetSetDef []

X

X

tp_base

PyTypeObject *

__base__

X

tp_dict

PyObject *

__dict__

?

tp_descr_get

descrgetfunc

__get__

X

tp_descr_set

descrsetfunc

__set__, __delete__

X

(tp_dictoffset)

Py_ssize_t

X

?

tp_init

initproc

__init__

X

X

X

tp_alloc

allocfunc

X

?

?

tp_new

newfunc

__new__

X

X

?

?

tp_free

freefunc

X

X

?

?

tp_is_gc

inquiry

X

X

<tp_bases>

PyObject *

__bases__

~

<tp_mro>

PyObject *

__mro__

~

[tp_cache]

PyObject *

[tp_subclasses]

void *

__subclasses__

[tp_weaklist]

PyObject *

(tp_del)

Destruktor

[tp_version_tag]

unsigned int

tp_finalize

Destruktor

__del__

X

tp_vectorcall

vectorcallfunc

[tp_watched]

unsigned char

Unter-Slots

Slot

Typ

spezielle Methoden

am_await

unaryfunc

__await__

am_aiter

unaryfunc

__aiter__

am_anext

unaryfunc

__anext__

am_send

sendfunc

nb_add

binaryfunc

__add__ __radd__

nb_inplace_add

binaryfunc

__iadd__

nb_subtract

binaryfunc

__sub__ __rsub__

nb_inplace_subtract

binaryfunc

__isub__

nb_multiply

binaryfunc

__mul__ __rmul__

nb_inplace_multiply

binaryfunc

__imul__

nb_remainder

binaryfunc

__mod__ __rmod__

nb_inplace_remainder

binaryfunc

__imod__

nb_divmod

binaryfunc

__divmod__ __rdivmod__

nb_power

ternaryfunc

__pow__ __rpow__

nb_inplace_power

ternaryfunc

__ipow__

nb_negative

unaryfunc

__neg__

nb_positive

unaryfunc

__pos__

nb_absolute

unaryfunc

__abs__

nb_bool

inquiry

__bool__

nb_invert

unaryfunc

__invert__

nb_lshift

binaryfunc

__lshift__ __rlshift__

nb_inplace_lshift

binaryfunc

__ilshift__

nb_rshift

binaryfunc

__rshift__ __rrshift__

nb_inplace_rshift

binaryfunc

__irshift__

nb_and

binaryfunc

__and__ __rand__

nb_inplace_and

binaryfunc

__iand__

nb_xor

binaryfunc

__xor__ __rxor__

nb_inplace_xor

binaryfunc

__ixor__

nb_or

binaryfunc

__or__ __ror__

nb_inplace_or

binaryfunc

__ior__

nb_int

unaryfunc

__int__

nb_reserved

void *

nb_float

unaryfunc

__float__

nb_floor_divide

binaryfunc

__floordiv__

nb_inplace_floor_divide

binaryfunc

__ifloordiv__

nb_true_divide

binaryfunc

__truediv__

nb_inplace_true_divide

binaryfunc

__itruediv__

nb_index

unaryfunc

__index__

nb_matrix_multiply

binaryfunc

__matmul__ __rmatmul__

nb_inplace_matrix_multiply

binaryfunc

__imatmul__

mp_length

lenfunc

__len__

mp_subscript

binaryfunc

__getitem__

mp_ass_subscript

objobjargproc

__setitem__, __delitem__

sq_length

lenfunc

__len__

sq_concat

binaryfunc

__add__

sq_repeat

ssizeargfunc

__mul__

sq_item

ssizeargfunc

__getitem__

sq_ass_item

ssizeobjargproc

__setitem__ __delitem__

sq_contains

objobjproc

__contains__

sq_inplace_concat

binaryfunc

__iadd__

sq_inplace_repeat

ssizeargfunc

__imul__

bf_getbuffer

getbufferproc()

__buffer__

bf_releasebuffer

releasebufferproc()

__release_buffer__

Slot-Typedefs

typedef

Parameter-Typen

Rückgabetyp

allocfunc

PyObject *

Destruktor

PyObject *

void

freefunc

void *

void

traverseproc

void *

int

newfunc

PyObject *

initproc

int

reprfunc

PyObject *

PyObject *

getattrfunc

const char *

PyObject *

setattrfunc

const char *

int

getattrofunc

PyObject *

setattrofunc

int

descrgetfunc

PyObject *

descrsetfunc

int

hashfunc

PyObject *

Py_hash_t

richcmpfunc

int

PyObject *

getiterfunc

PyObject *

PyObject *

iternextfunc

PyObject *

PyObject *

lenfunc

PyObject *

Py_ssize_t

getbufferproc

int

releasebufferproc

void

inquiry

PyObject *

int

unaryfunc

PyObject *

binaryfunc

PyObject *

ternaryfunc

PyObject *

ssizeargfunc

PyObject *

ssizeobjargproc

int

objobjproc

int

objobjargproc

int

Siehe Slot-Typedefs unten für weitere Details.

PyTypeObject-Definition

Die Strukturdefinition für PyTypeObject finden Sie in Include/cpython/object.h. Zur einfacheren Referenzierung wird hier die dort gefundene Definition wiederholt.

typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; /* For printing, in format "<module>.<name>" */
    Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

    /* Methods to implement standard operations */

    destructor tp_dealloc;
    Py_ssize_t tp_vectorcall_offset;
    getattrfunc tp_getattr;
    setattrfunc tp_setattr;
    PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
                                    or tp_reserved (Python 3) */
    reprfunc tp_repr;

    /* Method suites for standard classes */

    PyNumberMethods *tp_as_number;
    PySequenceMethods *tp_as_sequence;
    PyMappingMethods *tp_as_mapping;

    /* More standard operations (here for binary compatibility) */

    hashfunc tp_hash;
    ternaryfunc tp_call;
    reprfunc tp_str;
    getattrofunc tp_getattro;
    setattrofunc tp_setattro;

    /* Functions to access object as input/output buffer */
    PyBufferProcs *tp_as_buffer;

    /* Flags to define presence of optional/expanded features */
    unsigned long tp_flags;

    const char *tp_doc; /* Documentation string */

    /* Assigned meaning in release 2.0 */
    /* call function for all accessible objects */
    traverseproc tp_traverse;

    /* delete references to contained objects */
    inquiry tp_clear;

    /* Assigned meaning in release 2.1 */
    /* rich comparisons */
    richcmpfunc tp_richcompare;

    /* weak reference enabler */
    Py_ssize_t tp_weaklistoffset;

    /* Iterators */
    getiterfunc tp_iter;
    iternextfunc tp_iternext;

    /* Attribute descriptor and subclassing stuff */
    PyMethodDef *tp_methods;
    PyMemberDef *tp_members;
    PyGetSetDef *tp_getset;
    // Strong reference on a heap type, borrowed reference on a static type
    PyTypeObject *tp_base;
    PyObject *tp_dict;
    descrgetfunc tp_descr_get;
    descrsetfunc tp_descr_set;
    Py_ssize_t tp_dictoffset;
    initproc tp_init;
    allocfunc tp_alloc;
    newfunc tp_new;
    freefunc tp_free; /* Low-level free-memory routine */
    inquiry tp_is_gc; /* For PyObject_IS_GC */
    PyObject *tp_bases;
    PyObject *tp_mro; /* method resolution order */
    PyObject *tp_cache; /* no longer used */
    void *tp_subclasses;  /* for static builtin types this is an index */
    PyObject *tp_weaklist; /* not used for static builtin types */
    destructor tp_del;

    /* Type attribute cache version tag. Added in version 2.6.
     * If zero, the cache is invalid and must be initialized.
     */
    unsigned int tp_version_tag;

    destructor tp_finalize;
    vectorcallfunc tp_vectorcall;

    /* bitset of which type-watchers care about this type */
    unsigned char tp_watched;

    /* Number of tp_version_tag values used.
     * Set to _Py_ATTR_CACHE_UNUSED if the attribute cache is
     * disabled for this type (e.g. due to custom MRO entries).
     * Otherwise, limited to MAX_VERSIONS_PER_CLASS (defined elsewhere).
     */
    uint16_t tp_versions_used;
} PyTypeObject;

PyObject-Slots

Die Typobjektstruktur erweitert die PyVarObject-Struktur. Das Feld ob_size wird für dynamische Typen verwendet (erstellt durch type_new(), normalerweise aufgerufen von einer Klassendefinition). Beachten Sie, dass PyType_Type (der Metatyp) tp_itemsize initialisiert, was bedeutet, dass seine Instanzen (d. h. Typobjekte) das Feld ob_size *haben müssen*.

PyObject.ob_refcnt

Die Referenzanzahl des Typobjekts wird durch das Makro PyObject_HEAD_INIT mit 1 initialisiert. Beachten Sie, dass bei statisch allozierten Typobjekten die Instanzen des Typs (Objekte, deren ob_type auf den Typ zurückverweist) *nicht* als Referenzen gezählt werden. Aber bei dynamisch allozierten Typobjekten zählen die Instanzen *als* Referenzen.

Vererbung

Dieses Feld wird von Unterklassen nicht vererbt.

PyObject.ob_type

Dies ist der Typ des Typs, also sein Metatyp. Er wird durch das Argument für das Makro PyObject_HEAD_INIT initialisiert und sein Wert sollte normalerweise &PyType_Type sein. Bei dynamisch ladbaren Erweiterungsmodulen, die (zumindest) unter Windows verwendbar sein müssen, beschwert sich der Compiler jedoch, dass dies keine gültige Initialisierung ist. Daher ist die Konvention, NULL an das Makro PyObject_HEAD_INIT zu übergeben und dieses Feld explizit zu Beginn der Initialisierungsfunktion des Moduls zu initialisieren, bevor irgendetwas anderes getan wird. Dies geschieht typischerweise so:

Foo_Type.ob_type = &PyType_Type;

Dies sollte geschehen, bevor Instanzen des Typs erstellt werden. PyType_Ready() prüft, ob ob_type NULL ist und initialisiert es in diesem Fall mit dem Feld ob_type der Basisklasse. PyType_Ready() ändert dieses Feld nicht, wenn es ungleich null ist.

Vererbung

Dieses Feld wird von Unterklassen vererbt.

PyVarObject-Slots

PyVarObject.ob_size

Für statisch alloziierte Typobjekte sollte dies auf null initialisiert werden. Für dynamisch allocierte Typobjekte hat dieses Feld eine spezielle interne Bedeutung.

Dieses Feld sollte über das Makro Py_SIZE() zugegriffen werden.

Vererbung

Dieses Feld wird von Unterklassen nicht vererbt.

PyTypeObject-Slots

Jeder Slot hat einen Abschnitt, der die Vererbung beschreibt. Wenn PyType_Ready() einen Wert setzen kann, wenn das Feld auf NULL gesetzt ist, gibt es auch einen Abschnitt „Standard“.

const char *PyTypeObject.tp_name

Zeiger auf eine NUL-terminierte Zeichenkette mit dem Namen des Typs. Für Typen, die als globale Variablen eines Moduls zugänglich sind, sollte die Zeichenkette der vollständige Modulname, gefolgt von einem Punkt, gefolgt vom Typnamen sein; für eingebaute Typen sollte es nur der Typname sein. Wenn das Modul ein Untermodul eines Pakets ist, ist der vollständige Paketname Teil des vollständigen Modulnamens. Zum Beispiel sollte ein Typ namens T, der im Modul M im Unterpaket Q im Paket P definiert ist, den tp_name-Initialisierer "P.Q.M.T" haben.

Für dynamisch allocierte Typobjekte sollte dies nur der Typname sein, und der Modulname wird explizit im Typ-Dictionary unter dem Schlüssel '__module__' gespeichert.

Für statisch allocierte Typobjekte sollte das Feld tp_name einen Punkt enthalten. Alles vor dem letzten Punkt wird als Attribut __module__ zugänglich gemacht, und alles nach dem letzten Punkt wird als Attribut __name__ zugänglich gemacht.

Wenn kein Punkt vorhanden ist, wird das gesamte Feld tp_name als Attribut __name__ zugänglich gemacht, und das Attribut __module__ ist undefiniert (sofern es nicht explizit im Dictionary gesetzt wurde, wie oben erklärt). Das bedeutet, dass Ihr Typ nicht pickle-fähig ist. Außerdem wird er nicht in Modul-Dokumentationen aufgeführt, die mit pydoc erstellt wurden.

Dieses Feld darf nicht NULL sein. Es ist das einzige erforderliche Feld in PyTypeObject() (außer möglicherweise tp_itemsize).

Vererbung

Dieses Feld wird von Unterklassen nicht vererbt.

Py_ssize_t PyTypeObject.tp_basicsize
Py_ssize_t PyTypeObject.tp_itemsize

Diese Felder ermöglichen die Berechnung der Größe von Instanzen des Typs in Bytes.

Es gibt zwei Arten von Typen: Typen mit festen Instanzlängen haben ein tp_itemsize-Feld von Null, Typen mit variablen Instanzlängen haben ein tp_itemsize-Feld ungleich Null. Für einen Typ mit festen Instanzlängen haben alle Instanzen die gleiche Größe, angegeben in tp_basicsize. (Ausnahmen von dieser Regel können mit PyUnstable_Object_GC_NewWithExtraData() gemacht werden.)

Für einen Typ mit variablen Instanzlängen müssen die Instanzen ein Feld ob_size haben, und die Instanzgröße ist tp_basicsize plus N mal tp_itemsize, wobei N die „Länge“ des Objekts ist.

Funktionen wie PyObject_NewVar() nehmen den Wert von N als Argument und speichern ihn im Feld ob_size der Instanz. Beachten Sie, dass das Feld ob_size später für andere Zwecke verwendet werden kann. Zum Beispiel verwenden int-Instanzen die Bits von ob_size auf eine implementierungsdefinierte Weise; der zugrunde liegende Speicher und seine Größe sollten über PyLong_Export() abgerufen werden.

Hinweis

Auf das Feld ob_size sollte über die Makros Py_SIZE() und Py_SET_SIZE() zugegriffen werden.

Auch die Anwesenheit eines Feldes ob_size im Instanzlayout bedeutet nicht, dass die Instanzstruktur variable Länge hat. Zum Beispiel hat der Typ list feste Instanzlängen, aber diese Instanzen haben ein Feld ob_size. (Wie bei int, vermeiden Sie den direkten Zugriff auf ob_size von Listen. Rufen Sie stattdessen PyList_Size() auf.)

Die Größe tp_basicsize beinhaltet die für Daten des tp_base des Typs benötigte Größe, plus alle zusätzlichen Daten, die von jeder Instanz benötigt werden.

Der richtige Weg, tp_basicsize zu setzen, ist die Verwendung des sizeof-Operators auf der Struktur, die zur Deklaration des Instanzlayouts verwendet wird. Diese Struktur muss die Struktur enthalten, die zur Deklaration des Basistyps verwendet wird. Mit anderen Worten, tp_basicsize muss größer oder gleich dem tp_basicsize des Basis-Typs sein.

Da jeder Typ eine Unterklasse von object ist, muss diese Struktur PyObject oder PyVarObject enthalten (abhängig davon, ob ob_size enthalten sein soll). Diese werden normalerweise durch das Makro PyObject_HEAD oder PyObject_VAR_HEAD definiert, entsprechend.

Die Basisgröße beinhaltet nicht die Größe des GC-Headers, da dieser Header nicht Teil von PyObject_HEAD ist.

Für Fälle, in denen die zur Deklaration des Basistyps verwendete Struktur unbekannt ist, siehe PyType_Spec.basicsize und PyType_FromMetaclass().

Hinweise zur Ausrichtung

  • tp_basicsize muss ein Vielfaches von _Alignof(PyObject) sein. Wenn sizeof auf einer struct verwendet wird, die PyObject_HEAD enthält, wie empfohlen, stellt der Compiler dies sicher. Wenn keine C struct verwendet wird oder wenn Compiler-Erweiterungen wie __attribute__((packed)) verwendet werden, liegt dies in Ihrer Verantwortung.

  • Wenn die variablen Elemente eine bestimmte Ausrichtung erfordern, müssen tp_basicsize und tp_itemsize jeweils ein Vielfaches dieser Ausrichtung sein. Wenn beispielsweise der variable Teil eines Typs einen double speichert, liegt es in Ihrer Verantwortung, dass beide Felder ein Vielfaches von _Alignof(double) sind.

Vererbung

Diese Felder werden separat von Unterklassen vererbt. (Das heißt, wenn das Feld auf Null gesetzt ist, kopiert PyType_Ready() den Wert vom Basistyp, was darauf hinweist, dass die Instanzen keinen zusätzlichen Speicherplatz benötigen.)

Wenn der Basistyp ein tp_itemsize ungleich Null hat, ist es im Allgemeinen nicht sicher, tp_itemsize in einer Unterklasse auf einen anderen Wert ungleich Null zu setzen (obwohl dies von der Implementierung des Basistyps abhängt).

destructor PyTypeObject.tp_dealloc

Ein Zeiger auf die Instanzzerstörungsfunktion. Die Funktionssignatur lautet:

void tp_dealloc(PyObject *self);

Die Zerstörungsfunktion sollte alle Referenzen entfernen, die die Instanz besitzt (z. B. Py_CLEAR() aufrufen), alle von der Instanz besessenen Speicherpuffer freigeben und die Funktion tp_free des Typs aufrufen, um das Objekt selbst freizugeben.

Wenn Sie Funktionen aufrufen können, die den Fehlerindikator setzen können, müssen Sie PyErr_GetRaisedException() und PyErr_SetRaisedException() verwenden, um sicherzustellen, dass Sie einen bereits vorhandenen Fehlerindikator nicht überschreiben (die Deallokation könnte während der Verarbeitung eines anderen Fehlers aufgetreten sein).

static void
foo_dealloc(foo_object *self)
{
    PyObject *et, *ev, *etb;
    PyObject *exc = PyErr_GetRaisedException();
    ...
    PyErr_SetRaisedException(exc);
}

Der Deallocator selbst darf keine Ausnahme auslösen; wenn er auf einen Fehlerfall stößt, sollte er PyErr_FormatUnraisable() aufrufen, um eine nicht behebbare Ausnahme zu protokollieren (und zu löschen).

Es werden keine Garantien dafür übernommen, wann ein Objekt zerstört wird, außer

  • Python wird ein Objekt sofort oder einige Zeit nach dem Löschen der letzten Referenz auf das Objekt zerstören, es sei denn, sein Finalizer (tp_finalize) belebt das Objekt anschließend wieder.

  • Ein Objekt wird nicht zerstört, während es automatisch finalisiert (tp_finalize) oder automatisch gelöscht (tp_clear) wird.

CPython zerstört ein Objekt derzeit sofort mit Py_DECREF(), wenn der neue Referenzzähler null ist, aber dies kann sich in einer zukünftigen Version ändern.

Es wird empfohlen, PyObject_CallFinalizerFromDealloc() am Anfang von tp_dealloc aufzurufen, um sicherzustellen, dass das Objekt vor der Zerstörung immer finalisiert wird.

Wenn der Typ Garbage Collection unterstützt (das Flag Py_TPFLAGS_HAVE_GC gesetzt ist), sollte der Destruktor PyObject_GC_UnTrack() aufrufen, bevor er alle Mitgliedsfelder löscht.

Es ist zulässig, tp_clear von tp_dealloc aus aufzurufen, um Code-Duplizierung zu reduzieren und sicherzustellen, dass das Objekt vor der Zerstörung immer gelöscht wird. Beachten Sie, dass tp_clear möglicherweise bereits aufgerufen wurde.

Wenn der Typ heap-allokiert ist (Py_TPFLAGS_HEAPTYPE), sollte der Dealloziator die eigene Referenz auf sein Typobjekt (über Py_DECREF()) freigeben, nachdem der Typ-Dealloziator aufgerufen wurde. Siehe das folgende Beispiel.

static void
foo_dealloc(PyObject *op)
{
   foo_object *self = (foo_object *) op;
   PyObject_GC_UnTrack(self);
   Py_CLEAR(self->ref);
   Py_TYPE(self)->tp_free(self);
}

tp_dealloc muss den Ausnahmezustand unverändert lassen. Wenn er etwas aufrufen muss, das eine Ausnahme auslösen könnte, muss der Ausnahmezustand zuerst gesichert und später wiederhergestellt werden (nachdem Ausnahmen mit PyErr_WriteUnraisable() protokolliert wurden).

Beispiel

static void
foo_dealloc(PyObject *self)
{
    PyObject *exc = PyErr_GetRaisedException();

    if (PyObject_CallFinalizerFromDealloc(self) < 0) {
        // self was resurrected.
        goto done;
    }

    PyTypeObject *tp = Py_TYPE(self);

    if (tp->tp_flags & Py_TPFLAGS_HAVE_GC) {
        PyObject_GC_UnTrack(self);
    }

    // Optional, but convenient to avoid code duplication.
    if (tp->tp_clear && tp->tp_clear(self) < 0) {
        PyErr_WriteUnraisable(self);
    }

    // Any additional destruction goes here.

    tp->tp_free(self);
    self = NULL;  // In case PyErr_WriteUnraisable() is called below.

    if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) {
        Py_CLEAR(tp);
    }

done:
    // Optional, if something was called that might have raised an
    // exception.
    if (PyErr_Occurred()) {
        PyErr_WriteUnraisable(self);
    }
    PyErr_SetRaisedException(exc);
}

tp_dealloc kann von jedem Python-Thread aufgerufen werden, nicht nur von dem Thread, der das Objekt erstellt hat (wenn das Objekt Teil eines Referenzzählungszyklus wird, kann dieser Zyklus von einer Garbage Collection auf jedem Thread gesammelt werden). Dies ist für Python-API-Aufrufe kein Problem, da der Thread, auf dem tp_dealloc mit einem angehängten Thread-Zustand aufgerufen wird. Wenn das zu zerstörende Objekt wiederum Objekte aus einer anderen C-Bibliothek zerstört, ist jedoch darauf zu achten, dass die Zerstörung dieser Objekte auf dem Thread, der tp_dealloc aufgerufen hat, keine Annahmen der Bibliothek verletzt.

Vererbung

Dieses Feld wird von Unterklassen vererbt.

Siehe auch

Objektlebenszyklus für Details, wie dieser Slot mit anderen Slots zusammenhängt.

Py_ssize_t PyTypeObject.tp_vectorcall_offset

Ein optionaler Offset zu einer pro-Instanz-Funktion, die den Aufruf des Objekts mit dem Vectorcall-Protokoll implementiert, einer effizienteren Alternative zu tp_call.

Dieses Feld wird nur verwendet, wenn das Flag Py_TPFLAGS_HAVE_VECTORCALL gesetzt ist. In diesem Fall muss es eine positive Ganzzahl sein, die den Offset einer vectorcallfunc-Zeigers in der Instanz enthält.

Der vectorcallfunc-Zeiger kann NULL sein. In diesem Fall verhält sich die Instanz so, als wäre Py_TPFLAGS_HAVE_VECTORCALL nicht gesetzt: Der Aufruf der Instanz fällt auf tp_call zurück.

Jede Klasse, die Py_TPFLAGS_HAVE_VECTORCALL setzt, muss auch tp_call setzen und sicherstellen, dass dessen Verhalten mit der vectorcallfunc-Funktion konsistent ist. Dies kann durch Setzen von tp_call auf PyVectorcall_Call() erfolgen.

Geändert in Version 3.8: Vor Version 3.8 hieß dieses Feld tp_print. In Python 2.x wurde es zum Drucken auf eine Datei verwendet. In Python 3.0 bis 3.7 war es ungenutzt.

Geändert in Version 3.12: Vor Version 3.12 wurde es für veränderliche Heap-Typen nicht empfohlen, das Vectorcall-Protokoll zu implementieren. Wenn ein Benutzer __call__ in Python-Code setzt, wird nur tp_call aktualisiert, was wahrscheinlich zu Inkonsistenzen mit der Vectorcall-Funktion führt. Seit 3.12 deaktiviert das Setzen von __call__ die Vectorcall-Optimierung, indem das Flag Py_TPFLAGS_HAVE_VECTORCALL gelöscht wird.

Vererbung

Dieses Feld wird immer vererbt. Das Flag Py_TPFLAGS_HAVE_VECTORCALL wird jedoch nicht immer vererbt. Wenn es nicht gesetzt ist, verwendet die Unterklasse kein Vectorcall, es sei denn, PyVectorcall_Call() wird explizit aufgerufen.

getattrfunc PyTypeObject.tp_getattr

Ein optionaler Zeiger auf die Funktion zum Abrufen von Attributen als Zeichenkette.

Dieses Feld ist veraltet. Wenn es definiert ist, sollte es auf eine Funktion zeigen, die sich wie die Funktion tp_getattro verhält, aber einen C-String anstelle eines Python-String-Objekts als Attributnamen nimmt.

Vererbung

Gruppe: tp_getattr, tp_getattro

Dieses Feld wird zusammen mit tp_getattro von Unterklassen geerbt: Eine Unterklasse erbt sowohl tp_getattr als auch tp_getattro von ihrer Basisklasse, wenn die tp_getattr und tp_getattro der Unterklasse beide NULL sind.

setattrfunc PyTypeObject.tp_setattr

Ein optionaler Zeiger auf die Funktion zum Setzen und Löschen von Attributen.

Dieses Feld ist veraltet. Wenn es definiert ist, sollte es auf eine Funktion zeigen, die sich wie die Funktion tp_setattro verhält, aber einen C-String anstelle eines Python-String-Objekts als Attributnamen nimmt.

Vererbung

Gruppe: tp_setattr, tp_setattro

Dieses Feld wird zusammen mit tp_setattro von Unterklassen geerbt: Eine Unterklasse erbt sowohl tp_setattr als auch tp_setattro von ihrer Basisklasse, wenn die tp_setattr und tp_setattro der Unterklasse beide NULL sind.

PyAsyncMethods *PyTypeObject.tp_as_async

Zeiger auf eine zusätzliche Struktur, die Felder enthält, die nur für Objekte relevant sind, die awaitable und asynchrone Iteratorprotokolle auf C-Ebene implementieren. Siehe Asynchrone Objektstrukturen für Details.

Hinzugefügt in Version 3.5: Früher bekannt als tp_compare und tp_reserved.

Vererbung

Das Feld tp_as_async wird nicht vererbt, aber die enthaltenen Felder werden einzeln vererbt.

reprfunc PyTypeObject.tp_repr

Ein optionaler Zeiger auf eine Funktion, die die eingebaute Funktion repr() implementiert.

Die Signatur ist dieselbe wie für PyObject_Repr()

PyObject *tp_repr(PyObject *self);

Die Funktion muss eine Zeichenkette oder ein Unicode-Objekt zurückgeben. Idealerweise sollte diese Funktion eine Zeichenkette zurückgeben, die, wenn sie in eval() übergeben wird, mit einer geeigneten Umgebung ein Objekt mit demselben Wert zurückgibt. Wenn dies nicht machbar ist, sollte sie eine Zeichenkette zurückgeben, die mit '<' beginnt und mit '>' endet, aus der sowohl der Typ als auch der Wert des Objekts abgeleitet werden können.

Vererbung

Dieses Feld wird von Unterklassen vererbt.

Standard

Wenn dieses Feld nicht gesetzt ist, wird eine Zeichenkette der Form <%s object at %p> zurückgegeben, wobei %s durch den Typnamen und %p durch die Speicheradresse des Objekts ersetzt wird.

PyNumberMethods *PyTypeObject.tp_as_number

Zeiger auf eine zusätzliche Struktur, die Felder enthält, die nur für Objekte relevant sind, die das Zahlenprotokoll implementieren. Diese Felder sind in Zahlenobjektstrukturen dokumentiert.

Vererbung

Das Feld tp_as_number wird nicht vererbt, aber die enthaltenen Felder werden einzeln vererbt.

PySequenceMethods *PyTypeObject.tp_as_sequence

Zeiger auf eine zusätzliche Struktur, die Felder enthält, die nur für Objekte relevant sind, die das Sequenzprotokoll implementieren. Diese Felder sind in Sequenzobjektstrukturen dokumentiert.

Vererbung

Das Feld tp_as_sequence wird nicht vererbt, aber die enthaltenen Felder werden einzeln vererbt.

PyMappingMethods *PyTypeObject.tp_as_mapping

Zeiger auf eine zusätzliche Struktur, die Felder enthält, die nur für Objekte relevant sind, die das Mapping-Protokoll implementieren. Diese Felder sind in Mapping-Objektstrukturen dokumentiert.

Vererbung

Das Feld tp_as_mapping wird nicht vererbt, aber die enthaltenen Felder werden einzeln vererbt.

hashfunc PyTypeObject.tp_hash

Ein optionaler Zeiger auf eine Funktion, die die eingebaute Funktion hash() implementiert.

Die Signatur ist dieselbe wie für PyObject_Hash()

Py_hash_t tp_hash(PyObject *);

Der Wert -1 sollte nicht als normaler Rückgabewert zurückgegeben werden; wenn bei der Berechnung des Hash-Werts ein Fehler auftritt, sollte die Funktion eine Ausnahme setzen und -1 zurückgeben.

Wenn dieses Feld nicht gesetzt ist (und tp_richcompare nicht gesetzt ist), löst ein Versuch, das Objekt zu hashen, TypeError aus. Dies ist dasselbe, als würde es auf PyObject_HashNotImplemented() gesetzt.

Dieses Feld kann explizit auf PyObject_HashNotImplemented() gesetzt werden, um die Vererbung der Hash-Methode von einem übergeordneten Typ zu blockieren. Dies wird als Äquivalent zu __hash__ = None auf Python-Ebene interpretiert, wodurch isinstance(o, collections.Hashable) korrekt False zurückgibt. Beachten Sie, dass das Gegenteil auch gilt: das Setzen von __hash__ = None für eine Klasse auf Python-Ebene führt dazu, dass der tp_hash-Slot auf PyObject_HashNotImplemented() gesetzt wird.

Vererbung

Gruppe: tp_hash, tp_richcompare

Dieses Feld wird zusammen mit tp_richcompare von Unterklassen geerbt: Eine Unterklasse erbt sowohl tp_richcompare als auch tp_hash, wenn die tp_richcompare und tp_hash der Unterklasse beide NULL sind.

Standard

PyBaseObject_Type verwendet PyObject_GenericHash().

ternaryfunc PyTypeObject.tp_call

Ein optionaler Zeiger auf eine Funktion, die den Aufruf des Objekts implementiert. Dieser sollte NULL sein, wenn das Objekt nicht aufrufbar ist. Die Signatur ist dieselbe wie für PyObject_Call()

PyObject *tp_call(PyObject *self, PyObject *args, PyObject *kwargs);

Vererbung

Dieses Feld wird von Unterklassen vererbt.

reprfunc PyTypeObject.tp_str

Ein optionaler Zeiger auf eine Funktion, die die eingebaute Operation str() implementiert. (Beachten Sie, dass str jetzt ein Typ ist und str() den Konstruktor für diesen Typ aufruft. Dieser Konstruktor ruft PyObject_Str() auf, um die eigentliche Arbeit zu erledigen, und PyObject_Str() ruft diesen Handler auf.)

Die Signatur ist dieselbe wie für PyObject_Str()

PyObject *tp_str(PyObject *self);

Die Funktion muss eine Zeichenkette oder ein Unicode-Objekt zurückgeben. Sie sollte eine „freundliche“ Zeichenkettedarstellung des Objekts sein, da dies die Darstellung ist, die unter anderem von der Funktion print() verwendet wird.

Vererbung

Dieses Feld wird von Unterklassen vererbt.

Standard

Wenn dieses Feld nicht gesetzt ist, wird PyObject_Repr() aufgerufen, um eine Zeichenkettedarstellung zurückzugeben.

getattrofunc PyTypeObject.tp_getattro

Ein optionaler Zeiger auf die Funktion zum Abrufen von Attributen.

Die Signatur ist dieselbe wie für PyObject_GetAttr()

PyObject *tp_getattro(PyObject *self, PyObject *attr);

Es ist normalerweise praktisch, dieses Feld auf PyObject_GenericGetAttr() zu setzen, das die normale Methode zum Suchen von Objektattributen implementiert.

Vererbung

Gruppe: tp_getattr, tp_getattro

Dieses Feld wird zusammen mit tp_getattr von Unterklassen geerbt: Eine Unterklasse erbt sowohl tp_getattr als auch tp_getattro von ihrer Basisklasse, wenn die tp_getattr und tp_getattro der Unterklasse beide NULL sind.

Standard

PyBaseObject_Type verwendet PyObject_GenericGetAttr().

setattrofunc PyTypeObject.tp_setattro

Ein optionaler Zeiger auf die Funktion zum Setzen und Löschen von Attributen.

Die Signatur ist dieselbe wie für PyObject_SetAttr()

int tp_setattro(PyObject *self, PyObject *attr, PyObject *value);

Zusätzlich muss das Setzen von value auf NULL zum Löschen eines Attributs unterstützt werden. Es ist normalerweise praktisch, dieses Feld auf PyObject_GenericSetAttr() zu setzen, das die normale Methode zum Setzen von Objektattributen implementiert.

Vererbung

Gruppe: tp_setattr, tp_setattro

Dieses Feld wird zusammen mit tp_setattr von Unterklassen geerbt: Eine Unterklasse erbt sowohl tp_setattr als auch tp_setattro von ihrer Basisklasse, wenn die tp_setattr und tp_setattro der Unterklasse beide NULL sind.

Standard

PyBaseObject_Type verwendet PyObject_GenericSetAttr().

PyBufferProcs *PyTypeObject.tp_as_buffer

Zeiger auf eine zusätzliche Struktur, die Felder enthält, die nur für Objekte relevant sind, die die Puffer-Schnittstelle implementieren. Diese Felder sind in Pufferobjektstrukturen dokumentiert.

Vererbung

Das Feld tp_as_buffer wird nicht vererbt, aber die enthaltenen Felder werden einzeln vererbt.

unsigned long PyTypeObject.tp_flags

Dieses Feld ist eine Bitmaske verschiedener Flags. Einige Flags geben unterschiedliche Semantiken für bestimmte Situationen an; andere werden verwendet, um anzuzeigen, dass bestimmte Felder im Typobjekt (oder in den Erweiterungsstrukturen, auf die über tp_as_number, tp_as_sequence, tp_as_mapping und tp_as_buffer verwiesen wird) gültig sind, die historisch nicht immer vorhanden waren. Wenn ein solches Flag-Bit gelöscht ist, dürfen die von ihm geschützten Typfelder nicht zugegriffen werden und müssen stattdessen als Null oder NULL behandelt werden.

Vererbung

Die Vererbung dieses Feldes ist kompliziert. Die meisten Flag-Bits werden individuell vererbt, d.h. wenn der Basistyp ein Flag-Bit gesetzt hat, erbt der Subtyp dieses Flag-Bit. Die Flag-Bits, die sich auf Erweiterungsstrukturen beziehen, werden streng vererbt, wenn die Erweiterungsstruktur vererbt wird, d.h. der Wert des Flag-Bits des Basistyps wird zusammen mit einem Zeiger auf die Erweiterungsstruktur in den Subtyp kopiert. Das Flag-Bit Py_TPFLAGS_HAVE_GC wird zusammen mit den Feldern tp_traverse und tp_clear vererbt, d.h. wenn das Flag-Bit Py_TPFLAGS_HAVE_GC im Subtyp nicht gesetzt ist und die Felder tp_traverse und tp_clear im Subtyp existieren und den Wert NULL haben.

Standard

PyBaseObject_Type verwendet Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE.

Bitmasken

Die folgenden Bitmasken sind derzeit definiert; sie können mit dem Operator | zu einem Wert für das Feld tp_flags kombiniert werden. Das Makro PyType_HasFeature() nimmt einen Typ und einen Flags-Wert, tp und f, und prüft, ob tp->tp_flags & f ungleich Null ist.

Py_TPFLAGS_HEAPTYPE

Dieses Bit ist gesetzt, wenn das Typobjekt selbst auf dem Heap allokiert wird, z.B. Typen, die dynamisch mit PyType_FromSpec() erstellt werden. In diesem Fall wird das Feld ob_type seiner Instanzen als Verweis auf den Typ betrachtet, und das Typobjekt wird bei der Erstellung einer neuen Instanz mit INCREF und bei der Zerstörung einer Instanz mit DECREF inkrementiert (dies gilt nicht für Instanzen von Subtypen; nur der vom ob_type der Instanz referenzierte Typ wird inkrementiert oder dekrementiert). Heap-Typen müssen auch die Garbage Collection unterstützen, da sie mit ihrem eigenen Modulobjekt Zyklusreferenzen bilden können.

Vererbung

???

Py_TPFLAGS_BASETYPE

Dieses Bit ist gesetzt, wenn der Typ als Basistyp für einen anderen Typ verwendet werden kann. Wenn dieses Bit nicht gesetzt ist, kann der Typ nicht als Subtyp verwendet werden (ähnlich einer "finalen" Klasse in Java).

Vererbung

???

Py_TPFLAGS_READY

Dieses Bit ist gesetzt, wenn das Typobjekt durch PyType_Ready() vollständig initialisiert wurde.

Vererbung

???

Py_TPFLAGS_READYING

Dieses Bit ist gesetzt, während PyType_Ready() mit der Initialisierung des Typobjekts beschäftigt ist.

Vererbung

???

Py_TPFLAGS_HAVE_GC

Dieses Bit ist gesetzt, wenn das Objekt die Garbage Collection unterstützt. Wenn dieses Bit gesetzt ist, muss der Speicher für neue Instanzen (siehe tp_alloc) mit PyObject_GC_New oder PyType_GenericAlloc() allokiert und (siehe tp_free) mit PyObject_GC_Del() freigegeben werden. Weitere Informationen finden Sie in Abschnitt Unterstützung der zyklischen Garbage Collection.

Vererbung

Gruppe: Py_TPFLAGS_HAVE_GC, tp_traverse, tp_clear

Das Flag-Bit Py_TPFLAGS_HAVE_GC wird zusammen mit den Feldern tp_traverse und tp_clear vererbt, d.h. wenn das Flag-Bit Py_TPFLAGS_HAVE_GC im Subtyp nicht gesetzt ist und die Felder tp_traverse und tp_clear im Subtyp existieren und den Wert NULL haben.

Py_TPFLAGS_DEFAULT

Dies ist eine Bitmaske aller Bits, die für die Existenz bestimmter Felder im Typobjekt und seinen Erweiterungsstrukturen relevant sind. Derzeit sind folgende Bits enthalten: Py_TPFLAGS_HAVE_STACKLESS_EXTENSION.

Vererbung

???

Py_TPFLAGS_METHOD_DESCRIPTOR

Dieses Bit zeigt an, dass Objekte sich wie ungebundene Methoden verhalten.

Wenn dieses Flag für type(meth) gesetzt ist, dann

  • meth.__get__(obj, cls)(*args, **kwds) (wobei obj nicht None ist) muss äquivalent zu meth(obj, *args, **kwds) sein.

  • meth.__get__(None, cls)(*args, **kwds) muss äquivalent zu meth(*args, **kwds) sein.

Dieses Flag ermöglicht eine Optimierung für typische Methodenaufrufe wie obj.meth(): es vermeidet die Erstellung eines temporären "gebundenen Methoden"-Objekts für obj.meth.

Hinzugefügt in Version 3.8.

Vererbung

Dieses Flag wird niemals von Typen vererbt, bei denen das Flag Py_TPFLAGS_IMMUTABLETYPE nicht gesetzt ist. Für Erweiterungstypen wird es immer vererbt, wenn tp_descr_get vererbt wird.

Py_TPFLAGS_MANAGED_DICT

Dieses Bit zeigt an, dass Instanzen der Klasse ein Attribut __dict__ haben und dass der Platz für das Dictionary vom VM verwaltet wird.

Wenn dieses Flag gesetzt ist, sollte auch Py_TPFLAGS_HAVE_GC gesetzt sein.

Die Typ-Traversierungsfunktion muss PyObject_VisitManagedDict() aufrufen und ihre Clear-Funktion muss PyObject_ClearManagedDict() aufrufen.

Hinzugefügt in Version 3.12.

Vererbung

Dieses Flag wird vererbt, es sei denn, das Feld tp_dictoffset ist in einer Oberklasse gesetzt.

Py_TPFLAGS_MANAGED_WEAKREF

Dieses Bit zeigt an, dass Instanzen der Klasse schwach referenzierbar sein sollten.

Hinzugefügt in Version 3.12.

Vererbung

Dieses Flag wird vererbt, es sei denn, das Feld tp_weaklistoffset ist in einer Oberklasse gesetzt.

Py_TPFLAGS_ITEMS_AT_END

Nur verwendbar mit Typen variabler Größe, d.h. mit einem von Null verschiedenen tp_itemsize.

Zeigt an, dass der variable Teil einer Instanz dieses Typs am Ende des Speicherbereichs der Instanz liegt, in einem Offset von Py_TYPE(obj)->tp_basicsize (der sich in jeder Unterklasse unterscheiden kann).

Beim Setzen dieses Flags stellen Sie sicher, dass alle Oberklassen dieses Speicherlayout verwenden oder keine variable Größe haben. Python prüft dies nicht.

Hinzugefügt in Version 3.12.

Vererbung

Dieses Flag wird vererbt.

Py_TPFLAGS_LONG_SUBCLASS
Py_TPFLAGS_LIST_SUBCLASS
Py_TPFLAGS_TUPLE_SUBCLASS
Py_TPFLAGS_BYTES_SUBCLASS
Py_TPFLAGS_UNICODE_SUBCLASS
Py_TPFLAGS_DICT_SUBCLASS
Py_TPFLAGS_BASE_EXC_SUBCLASS
Py_TPFLAGS_TYPE_SUBCLASS

Diese Flags werden von Funktionen wie PyLong_Check() verwendet, um schnell zu prüfen, ob ein Typ eine Unterklasse eines integrierten Typs ist; solche spezifischen Prüfungen sind schneller als eine allgemeine Prüfung wie PyObject_IsInstance(). Benutzerdefinierte Typen, die von integrierten Typen erben, sollten ihre tp_flags entsprechend setzen, andernfalls verhält sich der Code, der mit solchen Typen interagiert, unterschiedlich, je nachdem, welche Art von Prüfung verwendet wird.

Py_TPFLAGS_HAVE_FINALIZE

Dieses Bit ist gesetzt, wenn der Slot tp_finalize in der Typstruktur vorhanden ist.

Hinzugefügt in Version 3.4.

Veraltet seit Version 3.8: Dieses Flag ist nicht mehr notwendig, da der Interpreter davon ausgeht, dass der Slot tp_finalize immer in der Typstruktur vorhanden ist.

Py_TPFLAGS_HAVE_VECTORCALL

Dieses Bit ist gesetzt, wenn die Klasse das Vektoraufrufprotokoll implementiert. Details finden Sie unter tp_vectorcall_offset.

Vererbung

Dieses Bit wird vererbt, wenn auch tp_call vererbt wird.

Hinzugefügt in Version 3.9.

Geändert in Version 3.12: Dieses Flag wird nun aus einer Klasse entfernt, wenn die Methode __call__() der Klasse neu zugewiesen wird.

Dieses Flag kann nun von veränderlichen Klassen vererbt werden.

Py_TPFLAGS_IMMUTABLETYPE

Dieses Bit ist für Typobjekte gesetzt, die unveränderlich sind: Typattribute können weder gesetzt noch gelöscht werden.

PyType_Ready() wendet dieses Flag automatisch auf statische Typen an.

Vererbung

Dieses Flag wird nicht vererbt.

Hinzugefügt in Version 3.10.

Py_TPFLAGS_DISALLOW_INSTANTIATION

Verhindert die Erstellung von Instanzen des Typs: setzen Sie tp_new auf NULL und erstellen Sie nicht den Schlüssel __new__ im Typ-Dictionary.

Das Flag muss vor der Erstellung des Typs gesetzt werden, nicht danach. Zum Beispiel muss es gesetzt werden, bevor PyType_Ready() für den Typ aufgerufen wird.

Das Flag wird automatisch auf statische Typen gesetzt, wenn tp_base NULL oder &PyBaseObject_Type ist und tp_new NULL ist.

Vererbung

Dieses Flag wird nicht vererbt. Allerdings werden Unterklassen nicht instanziierbar sein, es sei denn, sie stellen ein Nicht-NULL- tp_new bereit (was nur über die C-API möglich ist).

Hinweis

Um die direkte Instanziierung einer Klasse zu verhindern, aber die Instanziierung ihrer Unterklassen zu ermöglichen (z.B. für eine abstrakte Basisklasse), verwenden Sie dieses Flag nicht. Machen Sie stattdessen tp_new nur für Unterklassen erfolgreich.

Hinzugefügt in Version 3.10.

Py_TPFLAGS_MAPPING

Dieses Bit zeigt an, dass Instanzen der Klasse Mapping-Muster übereinstimmen können, wenn sie als Subjekt eines match-Blocks verwendet werden. Es wird automatisch gesetzt, wenn collections.abc.Mapping registriert oder als Unterklasse verwendet wird, und zurückgesetzt, wenn collections.abc.Sequence registriert wird.

Hinweis

Py_TPFLAGS_MAPPING und Py_TPFLAGS_SEQUENCE sind gegenseitig ausschließend; es ist ein Fehler, beide Flags gleichzeitig zu aktivieren.

Vererbung

Dieses Flag wird von Typen vererbt, die Py_TPFLAGS_SEQUENCE nicht bereits gesetzt haben.

Siehe auch

PEP 634 – Strukturelle Mustererkennung: Spezifikation

Hinzugefügt in Version 3.10.

Py_TPFLAGS_SEQUENCE

Dieses Bit zeigt an, dass Instanzen der Klasse Sequenzmuster übereinstimmen können, wenn sie als Subjekt eines match-Blocks verwendet werden. Es wird automatisch gesetzt, wenn collections.abc.Sequence registriert oder als Unterklasse verwendet wird, und zurückgesetzt, wenn collections.abc.Mapping registriert wird.

Hinweis

Py_TPFLAGS_MAPPING und Py_TPFLAGS_SEQUENCE sind gegenseitig ausschließend; es ist ein Fehler, beide Flags gleichzeitig zu aktivieren.

Vererbung

Dieses Flag wird von Typen vererbt, die Py_TPFLAGS_MAPPING nicht bereits gesetzt haben.

Siehe auch

PEP 634 – Strukturelle Mustererkennung: Spezifikation

Hinzugefügt in Version 3.10.

Py_TPFLAGS_VALID_VERSION_TAG

Intern. Dieses Flag darf nicht gesetzt oder gelöscht werden. Um anzuzeigen, dass eine Klasse geändert wurde, rufen Sie PyType_Modified() auf.

Warnung

Dieses Flag ist in Header-Dateien vorhanden, wird aber nicht verwendet. Es wird in einer zukünftigen Version von CPython entfernt.

const char *PyTypeObject.tp_doc

Ein optionaler Zeiger auf eine NUL-terminierte C-Zeichenkette, die den Docstring für dieses Typobjekt enthält. Dies wird als Attribut __doc__ für den Typ und seine Instanzen bereitgestellt.

Vererbung

Dieses Feld wird von Subtypen *nicht* vererbt.

traverseproc PyTypeObject.tp_traverse

Ein optionaler Zeiger auf eine Traversierungsfunktion für den Garbage Collector. Dies wird nur verwendet, wenn das Flag-Bit Py_TPFLAGS_HAVE_GC gesetzt ist. Die Signatur lautet

int tp_traverse(PyObject *self, visitproc visit, void *arg);

Weitere Informationen zu Pythons Garbage Collection finden Sie in Abschnitt Unterstützung der zyklischen Garbage Collection.

Der Zeiger tp_traverse wird vom Garbage Collector verwendet, um Referenzzyklen zu erkennen. Eine typische Implementierung einer tp_traverse-Funktion ruft einfach Py_VISIT() für jedes Mitglied der Instanz auf, das ein Python-Objekt ist und das die Instanz besitzt. Zum Beispiel ist dies die Funktion local_traverse() aus dem _thread-Erweiterungsmodul.

static int
local_traverse(PyObject *op, visitproc visit, void *arg)
{
    localobject *self = (localobject *) op;
    Py_VISIT(self->args);
    Py_VISIT(self->kw);
    Py_VISIT(self->dict);
    return 0;
}

Beachten Sie, dass Py_VISIT() nur für diejenigen Mitglieder aufgerufen wird, die an Referenzzyklen teilnehmen können. Obwohl es auch ein self->key-Mitglied gibt, kann dies nur NULL oder ein Python-String sein und daher nicht Teil eines Referenzzyklus sein.

Auf der anderen Seite, selbst wenn Sie wissen, dass ein Mitglied niemals Teil eines Zyklus sein kann, können Sie es als Debugging-Hilfe trotzdem besuchen, damit die Funktion gc.get_referents() des Moduls gc es einschließt.

Heap-Typen (Py_TPFLAGS_HEAPTYPE) müssen ihren Typ mit

Py_VISIT(Py_TYPE(self));

Dies ist nur seit Python 3.9 erforderlich. Um Python 3.8 und älter zu unterstützen, muss diese Zeile bedingt sein.

#if PY_VERSION_HEX >= 0x03090000
    Py_VISIT(Py_TYPE(self));
#endif

Wenn das Bit Py_TPFLAGS_MANAGED_DICT im Feld tp_flags gesetzt ist, muss die Traversierungsfunktion PyObject_VisitManagedDict() wie folgt aufrufen:

PyObject_VisitManagedDict((PyObject*)self, visit, arg);

Warnung

Bei der Implementierung von tp_traverse müssen nur die Mitglieder besucht werden, die die Instanz *besitzt* (indem sie starke Referenzen auf sie hat). Wenn ein Objekt beispielsweise schwache Referenzen über den Slot tp_weaklist unterstützt, darf der Zeiger, der die verkettete Liste unterstützt (worauf *tp_weaklist* zeigt), *nicht* besucht werden, da die Instanz keine direkten starken Referenzen auf die Elemente darin hält (da sie entfernt werden dürfen, auch wenn die Instanz noch lebt).

Beachten Sie, dass Py_VISIT() die Parameter visit und arg von local_traverse() mit diesen spezifischen Namen benötigt; benennen Sie sie nicht beliebig.

Instanzen von heap-allokierten Typen halten eine Referenz auf ihren Typ. Ihre Traversierungsfunktion muss daher entweder Py_TYPE(self) besuchen oder diese Verantwortung durch Aufruf von tp_traverse eines anderen heap-allokierten Typs (z.B. einer heap-allokierten Oberklasse) delegieren. Wenn sie dies nicht tun, wird der Typobjekt möglicherweise nicht vom Garbage Collector gesammelt.

Hinweis

Die Funktion tp_traverse kann von jedem Thread aufgerufen werden.

Geändert in Version 3.9: Heap-allokierte Typen müssen Py_TYPE(self) in tp_traverse besuchen. In früheren Python-Versionen konnte dies aufgrund von Bug 40217 zu Abstürzen in Unterklassen führen.

Vererbung

Gruppe: Py_TPFLAGS_HAVE_GC, tp_traverse, tp_clear

Dieses Feld wird von Subtypen zusammen mit tp_clear und dem Flag-Bit Py_TPFLAGS_HAVE_GC vererbt: das Flag-Bit, tp_traverse und tp_clear werden alle vom Basistyp geerbt, wenn sie im Subtyp alle Null sind.

inquiry PyTypeObject.tp_clear

Ein optionaler Zeiger auf eine Clear-Funktion. Die Signatur lautet

int tp_clear(PyObject *);

Der Zweck dieser Funktion ist es, Referenzzyklen zu brechen, die eine zyklische Isolierung verursachen, damit die Objekte sicher zerstört werden können. Ein geleertes Objekt ist ein teilweise zerstörtes Objekt; das Objekt ist nicht verpflichtet, Design-Invarianten zu erfüllen, die während der normalen Nutzung gelten.

tp_clear muss keine Referenzen auf Objekte löschen, die nicht an Referenzzyklen teilnehmen können, wie z.B. Python-Strings oder Python-Integers. Es kann jedoch praktisch sein, alle Referenzen zu löschen und die tp_dealloc-Funktion des Typs so zu schreiben, dass sie tp_clear aufruft, um Code-Duplizierung zu vermeiden. (Vorsicht: tp_clear wurde möglicherweise bereits aufgerufen. Bevorzugen Sie den Aufruf von idempotenten Funktionen wie Py_CLEAR().)

Jegliche nicht-triviale Bereinigung sollte in tp_finalize anstelle von tp_clear erfolgen.

Hinweis

Wenn tp_clear einen Referenzzyklus nicht brechen kann, können die Objekte in der zyklischen Isolierung ungesammelt bleiben ("lecken"). Siehe gc.garbage.

Hinweis

Referenzen (direkt und indirekt) könnten bereits geleert worden sein; sie sind nicht garantiert in einem konsistenten Zustand.

Hinweis

Die Funktion tp_clear kann von jedem Thread aufgerufen werden.

Hinweis

Es ist nicht garantiert, dass ein Objekt automatisch geleert wird, bevor sein Destruktor (tp_dealloc) aufgerufen wird.

Diese Funktion unterscheidet sich vom Destruktor (tp_dealloc) in folgenden Punkten

  • Der Zweck des Leerns eines Objekts ist es, Referenzen auf andere Objekte zu entfernen, die an einem Referenzzyklus beteiligt sein könnten. Der Zweck des Destruktors hingegen ist eine Obermenge: er muss *alle* von ihm besessenen Ressourcen freigeben, einschließlich Referenzen auf Objekte, die nicht an einem Referenzzyklus teilnehmen können (z.B. Ganzzahlen) sowie den eigenen Speicher des Objekts (durch Aufruf von tp_free).

  • Wenn tp_clear aufgerufen wird, können andere Objekte immer noch Referenzen auf das zu leerende Objekt halten. Aus diesem Grund darf tp_clear den eigenen Speicher des Objekts nicht freigeben (tp_free). Der Destruktor hingegen wird nur aufgerufen, wenn keine (starken) Referenzen existieren, und muss daher das Objekt selbst sicher zerstören, indem er es freigibt.

  • tp_clear wird möglicherweise niemals automatisch aufgerufen. Der Destruktor eines Objekts wird hingegen einige Zeit nachdem das Objekt nicht mehr erreichbar ist (d.h. es gibt keine Referenzen mehr auf das Objekt oder das Objekt ist Mitglied eines zyklischen Isolats), automatisch aufgerufen.

Es werden keine Garantien dafür übernommen, wann, ob oder wie oft Python ein Objekt automatisch bereinigt, außer

  • Python wird ein Objekt nicht automatisch bereinigen, wenn es erreichbar ist, d.h. wenn es eine Referenz darauf gibt und es kein Mitglied eines zyklischen Isolats ist.

  • Python wird ein Objekt nicht automatisch bereinigen, wenn es noch nicht automatisch finalisiert wurde (siehe tp_finalize). (Wenn der Finalizer das Objekt wiederbelebt hat, kann das Objekt vor der Bereinigung möglicherweise wieder automatisch finalisiert werden oder auch nicht.)

  • Wenn ein Objekt Mitglied eines zyklischen Isolats ist, wird Python es nicht automatisch bereinigen, wenn irgendein Mitglied des zyklischen Isolats noch nicht automatisch finalisiert wurde (tp_finalize).

  • Python wird ein Objekt erst zerstören, nachdem alle automatischen Aufrufe seiner tp_clear-Funktion zurückgekehrt sind. Dies stellt sicher, dass der Vorgang des Aufbrechens eines Referenzzyklus den self-Zeiger nicht ungültig macht, während tp_clear noch ausgeführt wird.

  • Python wird die Funktion tp_clear nicht mehrmals gleichzeitig aufrufen.

CPython bereinigt Objekte derzeit nur automatisch, wenn dies zur Unterbrechung von Referenzzyklen in einem zyklischen Isolat erforderlich ist, aber zukünftige Versionen könnten Objekte regelmäßig vor ihrer Zerstörung bereinigen.

Zusammengenommen müssen alle tp_clear-Funktionen im System alle Referenzzyklen aufbrechen. Dies ist subtil, und im Zweifelsfall sollte eine tp_clear-Funktion bereitgestellt werden. Zum Beispiel implementiert der Tupel-Typ keine tp_clear-Funktion, da nachweisbar ist, dass kein Referenzzyklus ausschließlich aus Tupeln bestehen kann. Daher sind die tp_clear-Funktionen anderer Typen dafür verantwortlich, jeden Zyklus aufzubrechen, der ein Tupel enthält. Dies ist nicht sofort ersichtlich und es gibt selten einen guten Grund, die Implementierung von tp_clear zu vermeiden.

Implementierungen von tp_clear sollten die Referenzen der Instanz auf ihre Mitglieder, die Python-Objekte sein können, aufheben und ihre Zeiger auf diese Mitglieder auf NULL setzen, wie im folgenden Beispiel

static int
local_clear(PyObject *op)
{
    localobject *self = (localobject *) op;
    Py_CLEAR(self->key);
    Py_CLEAR(self->args);
    Py_CLEAR(self->kw);
    Py_CLEAR(self->dict);
    return 0;
}

Das Makro Py_CLEAR() sollte verwendet werden, da das Löschen von Referenzen heikel ist: Die Referenz auf das enthaltene Objekt darf nicht freigegeben werden (mittels Py_DECREF()), bevor der Zeiger auf das enthaltene Objekt auf NULL gesetzt ist. Dies liegt daran, dass die Freigabe der Referenz dazu führen kann, dass das enthaltene Objekt zur Bereinigung markiert wird, was eine Kette von Bereinigungsaktivitäten auslösen kann, die die Ausführung von beliebigem Python-Code beinhalten kann (aufgrund von Finalizern oder Weakref-Callbacks, die mit dem enthaltenen Objekt verbunden sind). Wenn es möglich ist, dass solcher Code wieder *self* referenziert, ist es wichtig, dass der Zeiger auf das enthaltene Objekt zu diesem Zeitpunkt NULL ist, damit *self* weiß, dass das enthaltene Objekt nicht mehr verwendet werden kann. Das Makro Py_CLEAR() führt die Operationen in einer sicheren Reihenfolge aus.

Wenn das Bit Py_TPFLAGS_MANAGED_DICT im Feld tp_flags gesetzt ist, muss die Clear-Funktion PyObject_ClearManagedDict() wie folgt aufrufen

PyObject_ClearManagedDict((PyObject*)self);

Weitere Informationen zu Pythons Garbage Collection finden Sie in Abschnitt Unterstützung der zyklischen Garbage Collection.

Vererbung

Gruppe: Py_TPFLAGS_HAVE_GC, tp_traverse, tp_clear

Dieses Feld wird von Untertypen geerbt, zusammen mit tp_traverse und dem Flag-Bit Py_TPFLAGS_HAVE_GC: Das Flag-Bit, tp_traverse und tp_clear werden alle vom Basistyp geerbt, wenn sie im Untertyp alle Null sind.

Siehe auch

Objektlebenszyklus für Details, wie dieser Slot mit anderen Slots zusammenhängt.

richcmpfunc PyTypeObject.tp_richcompare

Ein optionaler Zeiger auf die Rich-Comparison-Funktion, deren Signatur lautet

PyObject *tp_richcompare(PyObject *self, PyObject *other, int op);

Der erste Parameter ist garantiert eine Instanz des Typs, der von PyTypeObject definiert wird.

Die Funktion sollte das Ergebnis des Vergleichs zurückgeben (normalerweise Py_True oder Py_False). Wenn der Vergleich undefiniert ist, muss sie Py_NotImplemented zurückgeben; wenn ein anderer Fehler aufgetreten ist, muss sie NULL zurückgeben und eine Ausnahmesituation setzen.

Die folgenden Konstanten sind definiert, um als dritter Argument für tp_richcompare und für PyObject_RichCompare() verwendet zu werden

Konstante

Vergleich

Py_LT

<

Py_LE

<=

Py_EQ

==

Py_NE

!=

Py_GT

>

Py_GE

>=

Das folgende Makro ist definiert, um das Schreiben von Rich-Comparison-Funktionen zu erleichtern

Py_RETURN_RICHCOMPARE(VAL_A, VAL_B, op)

Gibt Py_True oder Py_False aus der Funktion zurück, abhängig vom Ergebnis eines Vergleichs. VAL_A und VAL_B müssen durch C-Vergleichsoperatoren ordnungsfähig sein (z.B. können sie C-Integers oder -Floats sein). Das dritte Argument gibt die angeforderte Operation an, wie für PyObject_RichCompare().

Der zurückgegebene Wert ist eine neue starke Referenz.

Bei Fehlern wird eine Ausnahme gesetzt und die Funktion gibt NULL zurück.

Hinzugefügt in Version 3.7.

Vererbung

Gruppe: tp_hash, tp_richcompare

Dieses Feld wird von Untertypen geerbt, zusammen mit tp_hash: Ein Untertyp erbt tp_richcompare und tp_hash, wenn tp_richcompare und tp_hash des Untertyps beide NULL sind.

Standard

PyBaseObject_Type stellt eine tp_richcompare-Implementierung bereit, die geerbt werden kann. Wenn jedoch nur tp_hash definiert ist, wird nicht einmal die geerbte Funktion verwendet und Instanzen des Typs können an keinen Vergleichen teilnehmen.

Py_ssize_t PyTypeObject.tp_weaklistoffset

Während dieses Feld noch unterstützt wird, sollte Py_TPFLAGS_MANAGED_WEAKREF stattdessen verwendet werden, wenn möglich.

Wenn die Instanzen dieses Typs schwach referenzierbar sind, ist dieses Feld größer als Null und enthält den Offset in der Instanzstruktur des Schwachreferenzlistenkopfs (GC-Header, falls vorhanden, wird ignoriert); dieser Offset wird von PyObject_ClearWeakRefs() und den PyWeakref_*-Funktionen verwendet. Die Instanzstruktur muss ein Feld vom Typ PyObject* enthalten, das mit NULL initialisiert wird.

Verwechseln Sie dieses Feld nicht mit tp_weaklist; das ist der Listen-Kopf für schwache Referenzen auf das Typobjekt selbst.

Es ist ein Fehler, sowohl das Bit Py_TPFLAGS_MANAGED_WEAKREF als auch tp_weaklistoffset zu setzen.

Vererbung

Dieses Feld wird von Untertypen geerbt, siehe jedoch die unten aufgeführten Regeln. Ein Untertyp kann diesen Offset überschreiben; dies bedeutet, dass der Untertyp einen anderen Schwachreferenzlisten-Kopf als der Basistyp verwendet. Da der Listen-Kopf immer über tp_weaklistoffset gefunden wird, sollte dies kein Problem darstellen.

Standard

Wenn das Bit Py_TPFLAGS_MANAGED_WEAKREF im Feld tp_flags gesetzt ist, wird tp_weaklistoffset auf einen negativen Wert gesetzt, um anzuzeigen, dass die Verwendung dieses Feldes unsicher ist.

getiterfunc PyTypeObject.tp_iter

Ein optionaler Zeiger auf eine Funktion, die einen Iterator für das Objekt zurückgibt. Seine Anwesenheit signalisiert normalerweise, dass die Instanzen dieses Typs iterierbar sind (obwohl Sequenzen ohne diese Funktion iterierbar sein können).

Diese Funktion hat die gleiche Signatur wie PyObject_GetIter()

PyObject *tp_iter(PyObject *self);

Vererbung

Dieses Feld wird von Unterklassen vererbt.

iternextfunc PyTypeObject.tp_iternext

Ein optionaler Zeiger auf eine Funktion, die das nächste Element in einem Iterator zurückgibt. Die Signatur lautet

PyObject *tp_iternext(PyObject *self);

Wenn der Iterator erschöpft ist, muss er NULL zurückgeben; eine StopIteration-Ausnahme kann gesetzt sein oder auch nicht. Wenn ein anderer Fehler auftritt, muss er ebenfalls NULL zurückgeben. Seine Anwesenheit signalisiert, dass die Instanzen dieses Typs Iteratoren sind.

Iterator-Typen sollten auch die Funktion tp_iter definieren, und diese Funktion sollte die Iterator-Instanz selbst zurückgeben (nicht eine neue Iterator-Instanz).

Diese Funktion hat die gleiche Signatur wie PyIter_Next().

Vererbung

Dieses Feld wird von Unterklassen vererbt.

struct PyMethodDef *PyTypeObject.tp_methods

Ein optionaler Zeiger auf ein statisches, mit NULL abgeschlossenes Array von PyMethodDef-Strukturen, die reguläre Methoden dieses Typs deklarieren.

Für jeden Eintrag im Array wird ein Eintrag im Wörterbuch des Typs (siehe tp_dict unten) erstellt, der einen Methodendeskriptor enthält.

Vererbung

Dieses Feld wird von Untertypen nicht geerbt (Methoden werden über einen anderen Mechanismus geerbt).

struct PyMemberDef *PyTypeObject.tp_members

Ein optionaler Zeiger auf ein statisches, mit NULL abgeschlossenes Array von PyMemberDef-Strukturen, die reguläre Datenmember (Felder oder Slots) von Instanzen dieses Typs deklarieren.

Für jeden Eintrag im Array wird ein Eintrag im Wörterbuch des Typs (siehe tp_dict unten) erstellt, der einen Member-Deskriptor enthält.

Vererbung

Dieses Feld wird von Untertypen nicht geerbt (Member werden über einen anderen Mechanismus geerbt).

struct PyGetSetDef *PyTypeObject.tp_getset

Ein optionaler Zeiger auf ein statisches, mit NULL abgeschlossenes Array von PyGetSetDef-Strukturen, die berechnete Attribute von Instanzen dieses Typs deklarieren.

Für jeden Eintrag im Array wird ein Eintrag im Wörterbuch des Typs (siehe tp_dict unten) erstellt, der einen Getset-Deskriptor enthält.

Vererbung

Dieses Feld wird von Untertypen nicht geerbt (berechnete Attribute werden über einen anderen Mechanismus geerbt).

PyTypeObject *PyTypeObject.tp_base

Ein optionaler Zeiger auf einen Basistyp, von dem Typ-Eigenschaften geerbt werden. Auf dieser Ebene wird nur Einfachvererbung unterstützt; Mehrfachvererbung erfordert das dynamische Erstellen eines Typobjekts durch Aufruf der Metaklasse.

Hinweis

Die Initialisierung von Slots unterliegt den Regeln der Initialisierung von Globals. C99 verlangt, dass die Initialisierer "Adresskonstanten" sind. Funktionsdeskriptoren wie PyType_GenericNew(), mit impliziter Umwandlung in einen Zeiger, sind gültige C99-Adresskonstanten.

Der unäre '&'-Operator, angewendet auf eine nicht-statische Variable wie PyBaseObject_Type, muss jedoch keine Adresskonstante ergeben. Compiler können dies unterstützen (gcc tut dies), MSVC nicht. Beide Compiler sind in diesem speziellen Verhalten streng standardkonform.

Folglich sollte tp_base in der Init-Funktion des Erweiterungsmoduls gesetzt werden.

Vererbung

Dieses Feld wird von Untertypen nicht geerbt (offensichtlich).

Standard

Dieses Feld hat den Standardwert &PyBaseObject_Type (was für Python-Programmierer als Typ object bekannt ist).

PyObject *PyTypeObject.tp_dict

Das Wörterbuch des Typs wird hier von PyType_Ready() gespeichert.

Dieses Feld sollte normalerweise vor dem Aufruf von PyType_Ready auf NULL initialisiert werden; es kann auch mit einem Wörterbuch initialisiert werden, das anfängliche Attribute für den Typ enthält. Nachdem PyType_Ready() den Typ initialisiert hat, können zusätzliche Attribute für den Typ zu diesem Wörterbuch hinzugefügt werden, sofern sie nicht überladenen Operationen entsprechen (wie __add__()). Sobald die Initialisierung für den Typ abgeschlossen ist, sollte dieses Feld als schreibgeschützt behandelt werden.

Einige Typen speichern ihr Wörterbuch möglicherweise nicht in diesem Slot. Verwenden Sie PyType_GetDict(), um das Wörterbuch für einen beliebigen Typ abzurufen.

Geändert in Version 3.12: Interne Details: Für statische eingebaute Typen ist dies immer NULL. Stattdessen wird das Wörterbuch für solche Typen auf PyInterpreterState gespeichert. Verwenden Sie PyType_GetDict(), um das Wörterbuch für einen beliebigen Typ abzurufen.

Vererbung

Dieses Feld wird von Untertypen nicht geerbt (obwohl die hier definierten Attribute über einen anderen Mechanismus geerbt werden).

Standard

Wenn dieses Feld NULL ist, weist PyType_Ready() ihm ein neues Wörterbuch zu.

Warnung

Es ist nicht sicher, PyDict_SetItem() auf tp_dict anzuwenden oder es anderweitig mit der C-API für Wörterbücher zu ändern.

descrgetfunc PyTypeObject.tp_descr_get

Ein optionaler Zeiger auf eine "Deskriptor-Get"-Funktion.

Die Funktion Signatur lautet

PyObject * tp_descr_get(PyObject *self, PyObject *obj, PyObject *type);

Vererbung

Dieses Feld wird von Unterklassen vererbt.

descrsetfunc PyTypeObject.tp_descr_set

Ein optionaler Zeiger auf eine Funktion zum Setzen und Löschen eines Deskriptorwerts.

Die Funktion Signatur lautet

int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);

Das *value*-Argument wird auf NULL gesetzt, um den Wert zu löschen.

Vererbung

Dieses Feld wird von Unterklassen vererbt.

Py_ssize_t PyTypeObject.tp_dictoffset

Während dieses Feld noch unterstützt wird, sollte Py_TPFLAGS_MANAGED_DICT stattdessen verwendet werden, wenn möglich.

Wenn die Instanzen dieses Typs ein Wörterbuch mit Instanzvariablen haben, ist dieses Feld ungleich Null und enthält den Offset in den Instanzen des Typs des Instanzvariablen-Wörterbuchs; dieser Offset wird von PyObject_GenericGetAttr() verwendet.

Verwechseln Sie dieses Feld nicht mit tp_dict; das ist das Wörterbuch für Attribute des Typobjekts selbst.

Der Wert gibt den Offset des Wörterbuchs vom Anfang der Instanzstruktur an.

tp_dictoffset sollte als schreibgeschützt betrachtet werden. Um den Zeiger auf das Wörterbuch zu erhalten, rufen Sie PyObject_GenericGetDict() auf. Das Aufrufen von PyObject_GenericGetDict() kann die Zuweisung von Speicher für das Wörterbuch erfordern, daher kann es effizienter sein, PyObject_GetAttr() aufzurufen, wenn auf ein Attribut des Objekts zugegriffen wird.

Es ist ein Fehler, sowohl das Bit Py_TPFLAGS_MANAGED_DICT als auch tp_dictoffset zu setzen.

Vererbung

Dieses Feld wird von Untertypen geerbt. Ein Untertyp sollte diesen Offset nicht überschreiben; dies könnte unsicher sein, wenn C-Code versucht, auf das Dictionary am vorherigen Offset zuzugreifen. Um die Vererbung ordnungsgemäß zu unterstützen, verwenden Sie Py_TPFLAGS_MANAGED_DICT.

Standard

Dieser Slot hat keinen Standardwert. Für statische Typen wird, wenn das Feld NULL ist, kein __dict__ für Instanzen erstellt.

Wenn das Py_TPFLAGS_MANAGED_DICT Bit im Feld tp_flags gesetzt ist, wird tp_dictoffset auf -1 gesetzt, um anzuzeigen, dass die Verwendung dieses Feldes unsicher ist.

initproc PyTypeObject.tp_init

Ein optionaler Zeiger auf eine Instanzinitialisierungsfunktion.

Diese Funktion entspricht der Methode __init__() von Klassen. Wie bei __init__() ist es möglich, eine Instanz zu erstellen, ohne __init__() aufzurufen, und es ist möglich, eine Instanz neu zu initialisieren, indem ihre __init__() Methode erneut aufgerufen wird.

Die Funktion Signatur lautet

int tp_init(PyObject *self, PyObject *args, PyObject *kwds);

Das Argument `self` ist die zu initialisierende Instanz; die Argumente `args` und `kwds` repräsentieren Positions- und Schlüsselwortargumente des Aufrufs von __init__().

Die Funktion tp_init, falls nicht NULL, wird aufgerufen, wenn eine Instanz normalerweise durch Aufrufen ihres Typs erstellt wird, nachdem die Funktion tp_new des Typs eine Instanz des Typs zurückgegeben hat. Wenn die Funktion tp_new eine Instanz eines anderen Typs zurückgibt, der kein Untertyp des ursprünglichen Typs ist, wird keine Funktion tp_init aufgerufen; wenn tp_new eine Instanz eines Untertyps des ursprünglichen Typs zurückgibt, wird die Funktion tp_init des Untertyps aufgerufen.

Gibt bei Erfolg 0 zurück, bei einem Fehler -1 und setzt eine Ausnahme.

Vererbung

Dieses Feld wird von Unterklassen vererbt.

Standard

Für statische Typen hat dieses Feld keinen Standardwert.

allocfunc PyTypeObject.tp_alloc

Ein optionaler Zeiger auf eine Instanzzuweisungsfunktion.

Die Funktion Signatur lautet

PyObject *tp_alloc(PyTypeObject *self, Py_ssize_t nitems);

Vererbung

Statische Untertypen erben diesen Slot, der PyType_GenericAlloc() ist, wenn er von object geerbt wird.

Heap-Untertypen erben diesen Slot nicht.

Standard

Für Heap-Untertypen ist dieses Feld immer auf PyType_GenericAlloc() gesetzt.

Für statische Untertypen wird dieser Slot geerbt (siehe oben).

newfunc PyTypeObject.tp_new

Ein optionaler Zeiger auf eine Instanzerstellungsfunktion.

Die Funktion Signatur lautet

PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds);

Das Argument `subtype` ist der Typ des zu erstellenden Objekts; die Argumente `args` und `kwds` repräsentieren Positions- und Schlüsselwortargumente des Aufrufs des Typs. Beachten Sie, dass `subtype` nicht mit dem Typ übereinstimmen muss, dessen Funktion tp_new aufgerufen wird; es kann ein Untertyp dieses Typs sein (aber kein unrelateder Typ).

Die Funktion tp_new sollte subtype->tp_alloc(subtype, nitems) aufrufen, um Speicher für das Objekt zuzuweisen, und dann nur so viel weitere Initialisierung vornehmen, wie absolut notwendig ist. Initialisierung, die sicher ignoriert oder wiederholt werden kann, sollte in den Handler tp_init verschoben werden. Eine gute Faustregel ist, dass für unveränderliche Typen die gesamte Initialisierung in tp_new erfolgen sollte, während für veränderliche Typen der Großteil der Initialisierung auf tp_init verschoben werden sollte.

Setzen Sie das Flag Py_TPFLAGS_DISALLOW_INSTANTIATION, um die Erstellung von Instanzen des Typs in Python zu verhindern.

Vererbung

Dieses Feld wird von Untertypen geerbt, mit der Ausnahme, dass es nicht von statischen Typen geerbt wird, deren tp_base NULL oder &PyBaseObject_Type ist.

Standard

Für statische Typen hat dieses Feld keinen Standardwert. Das bedeutet, wenn der Slot als NULL definiert ist, kann der Typ nicht aufgerufen werden, um neue Instanzen zu erstellen; wahrscheinlich gibt es eine andere Möglichkeit, Instanzen zu erstellen, wie z. B. eine Factory-Funktion.

freefunc PyTypeObject.tp_free

Ein optionaler Zeiger auf eine Instanzdeallokierungsfunktion. Ihre Signatur ist

void tp_free(void *self);

Diese Funktion muss den von tp_alloc zugewiesenen Speicher freigeben.

Vererbung

Statische Untertypen erben diesen Slot, der PyObject_Free() ist, wenn er von object geerbt wird. Ausnahme: Wenn der Typ Garbage Collection unterstützt (d. h. das Flag Py_TPFLAGS_HAVE_GC im Feld tp_flags gesetzt ist) und er PyObject_Free() erben würde, wird dieser Slot nicht geerbt, sondern standardmäßig auf PyObject_GC_Del() gesetzt.

Heap-Untertypen erben diesen Slot nicht.

Standard

Für Heap-Untertypen ist dieser Slot standardmäßig ein Deallokator, der zu PyType_GenericAlloc() und dem Wert des Flags Py_TPFLAGS_HAVE_GC passt.

Für statische Untertypen wird dieser Slot geerbt (siehe oben).

inquiry PyTypeObject.tp_is_gc

Ein optionaler Zeiger auf eine Funktion, die vom Garbage Collector aufgerufen wird.

Der Garbage Collector muss wissen, ob ein bestimmtes Objekt sammelbar ist oder nicht. Normalerweise reicht es aus, das Feld tp_flags des Typs des Objekts zu betrachten und das Bit des Flags Py_TPFLAGS_HAVE_GC zu prüfen. Einige Typen haben jedoch eine Mischung aus statisch und dynamisch zugewiesenen Instanzen, und die statisch zugewiesenen Instanzen sind nicht sammelbar. Solche Typen sollten diese Funktion definieren; sie sollte 1 für eine sammelbare Instanz und 0 für eine nicht sammelbare Instanz zurückgeben. Die Signatur ist

int tp_is_gc(PyObject *self);

(Das einzige Beispiel hierfür sind Typen selbst. Der Metatyp, PyType_Type, definiert diese Funktion, um zwischen statisch und dynamisch zugewiesenen Typen zu unterscheiden.)

Vererbung

Dieses Feld wird von Unterklassen vererbt.

Standard

Dieser Slot hat keinen Standardwert. Wenn dieses Feld NULL ist, wird Py_TPFLAGS_HAVE_GC als funktionales Äquivalent verwendet.

PyObject *PyTypeObject.tp_bases

Tupel der Basistypen.

Dieses Feld sollte auf NULL gesetzt und als schreibgeschützt behandelt werden. Python füllt es aus, wenn der Typ initialisiert wird.

Für dynamisch erstellte Klassen kann der Slot Py_tp_bases anstelle des Arguments `bases` von PyType_FromSpecWithBases() verwendet werden. Die Argumentform wird bevorzugt.

Warnung

Mehrfachvererbung funktioniert für statisch definierte Typen nicht gut. Wenn Sie tp_bases auf ein Tupel setzen, wird Python keinen Fehler auslösen, aber einige Slots werden nur vom ersten Basis-Typ geerbt.

Vererbung

Dieses Feld wird nicht geerbt.

PyObject *PyTypeObject.tp_mro

Tupel, das die erweiterte Menge der Basistypen enthält, beginnend mit dem Typ selbst und endend mit object, in der Method Resolution Order.

Dieses Feld sollte auf NULL gesetzt und als schreibgeschützt behandelt werden. Python füllt es aus, wenn der Typ initialisiert wird.

Vererbung

Dieses Feld wird nicht geerbt; es wird neu von PyType_Ready() berechnet.

PyObject *PyTypeObject.tp_cache

Unbenutzt. Nur für interne Verwendung.

Vererbung

Dieses Feld wird nicht geerbt.

void *PyTypeObject.tp_subclasses

Eine Sammlung von Unterklassen. Nur für interne Verwendung. Kann ein ungültiger Zeiger sein.

Um eine Liste von Unterklassen zu erhalten, rufen Sie die Python-Methode __subclasses__() auf.

Geändert in Version 3.12: Für einige Typen enthält dieses Feld kein gültiges PyObject*. Der Typ wurde in void* geändert, um dies anzuzeigen.

Vererbung

Dieses Feld wird nicht geerbt.

PyObject *PyTypeObject.tp_weaklist

Kopf der Liste von Weak References, für Weak References auf dieses Typobjekt. Nicht geerbt. Nur für interne Verwendung.

Geändert in Version 3.12: Interna-Details: Für die statischen eingebauten Typen ist dies immer NULL, auch wenn Weak References hinzugefügt werden. Stattdessen werden die Weak References für jeden auf PyInterpreterState gespeichert. Verwenden Sie die öffentliche C-API oder das interne Makro _PyObject_GET_WEAKREFS_LISTPTR(), um den Unterschied zu vermeiden.

Vererbung

Dieses Feld wird nicht geerbt.

destructor PyTypeObject.tp_del

Dieses Feld ist veraltet. Verwenden Sie stattdessen tp_finalize.

unsigned int PyTypeObject.tp_version_tag

Wird zur Indizierung des Methodencaches verwendet. Nur für interne Verwendung.

Vererbung

Dieses Feld wird nicht geerbt.

destructor PyTypeObject.tp_finalize

Ein optionaler Zeiger auf eine Instanzfinalisierungsfunktion. Dies ist die C-Implementierung der speziellen Methode __del__(). Ihre Signatur ist

void tp_finalize(PyObject *self);

Der Hauptzweck der Finalisierung ist die Durchführung von nicht-trivialen Bereinigungsarbeiten, die vor der Zerstörung des Objekts durchgeführt werden müssen, während das Objekt und alle anderen Objekte, auf die es direkt oder indirekt verweist, sich noch in einem konsistenten Zustand befinden. Der Finalizer darf beliebigen Python-Code ausführen.

Bevor Python ein Objekt automatisch finalisiert, könnten einige der direkten oder indirekten Referenten des Objekts selbst automatisch finalisiert worden sein. Keiner der Referenten wurde jedoch automatisch gelöscht (siehe tp_clear).

Andere nicht-finalisierte Objekte könnten immer noch ein finalisiertes Objekt verwenden, daher muss der Finalizer das Objekt in einem sinnvollen Zustand hinterlassen (z. B. sind die Invarianten noch erfüllt).

Hinweis

Nachdem Python ein Objekt automatisch finalisiert hat, kann Python beginnen, das Objekt und seine Referenten automatisch zu löschen (siehe tp_clear) (direkt und indirekt). Gelöschte Objekte befinden sich nicht zwangsläufig in einem konsistenten Zustand; ein finalisiertes Objekt muss gelöschte Referenten tolerieren können.

Hinweis

Es gibt keine Garantie, dass ein Objekt automatisch finalisiert wird, bevor sein Destruktor (tp_dealloc) aufgerufen wird. Es wird empfohlen, PyObject_CallFinalizerFromDealloc() am Anfang von tp_dealloc aufzurufen, um sicherzustellen, dass das Objekt vor der Zerstörung immer finalisiert wird.

Hinweis

Die Funktion tp_finalize kann von jedem Thread aus aufgerufen werden, obwohl der GIL gehalten wird.

Hinweis

Die Funktion tp_finalize kann während des Herunterfahrens aufgerufen werden, nachdem einige globale Variablen gelöscht wurden. Siehe die Dokumentation der Methode __del__() für Details.

Wenn Python ein Objekt finalisiert, verhält es sich wie der folgende Algorithmus:

  1. Python kann das Objekt als *finalisiert* markieren. Derzeit markiert Python immer Objekte, deren Typ Garbage Collection unterstützt (d. h. das Flag Py_TPFLAGS_HAVE_GC ist im Feld tp_flags gesetzt) und markiert niemals andere Arten von Objekten; dies könnte sich in einer zukünftigen Version ändern.

  2. Wenn das Objekt nicht als *finalisiert* markiert ist und seine Finalisierungsfunktion tp_finalize nicht NULL ist, wird die Finalisierungsfunktion aufgerufen.

  3. Wenn die Finalisierungsfunktion aufgerufen wurde und die Finalisierung das Objekt erreichbar gemacht hat (d. h. es gibt eine Referenz auf das Objekt und es ist kein Mitglied eines zyklischen Isolats), dann hat die Finalisierung das Objekt *wiederbelebt*. Es ist nicht spezifiziert, ob die Finalisierung das Objekt auch durch Hinzufügen einer neuen Referenz wiederbeleben kann, die das Objekt nicht erreichbar macht, d. h. das Objekt ist (immer noch) ein Mitglied eines zyklischen Isolats.

  4. Wenn die Finalisierung das Objekt wiederbelebt hat, wird die ausstehende Zerstörung des Objekts abgebrochen und die Markierung *finalisiert* des Objekts kann, falls vorhanden, entfernt werden. Derzeit entfernt Python niemals die Markierung *finalisiert*; dies könnte sich in einer zukünftigen Version ändern.

Unter *automatischer Finalisierung* versteht man jede Finalisierung, die von Python durchgeführt wird, außer über Aufrufe von PyObject_CallFinalizer() oder PyObject_CallFinalizerFromDealloc(). Es werden keine Garantien gegeben, wann, ob oder wie oft ein Objekt automatisch finalisiert wird, außer

  • Python wird ein Objekt nicht automatisch finalisieren, wenn es erreichbar ist, d. h. es gibt eine Referenz darauf und es ist kein Mitglied eines zyklischen Isolats.

  • Python wird ein Objekt nicht automatisch finalisieren, wenn die Finalisierung das Objekt nicht als *finalisiert* markieren würde. Derzeit gilt dies für Objekte, deren Typ keine Garbage Collection unterstützt, d. h. das Flag Py_TPFLAGS_HAVE_GC ist nicht gesetzt. Solche Objekte können immer noch manuell finalisiert werden, indem PyObject_CallFinalizer() oder PyObject_CallFinalizerFromDealloc() aufgerufen wird.

  • Python wird keine zwei Mitglieder eines zyklischen Isolats gleichzeitig automatisch finalisieren.

  • Python wird ein Objekt nicht automatisch finalisieren, nachdem es das Objekt automatisch gelöscht hat (siehe tp_clear).

  • Wenn ein Objekt Mitglied eines zyklischen Isolats ist, wird Python es nicht automatisch finalisieren, nachdem es ein anderes Mitglied automatisch gelöscht hat (siehe tp_clear).

  • Python wird alle Mitglieder eines zyklischen Isolats automatisch finalisieren, bevor es eines davon automatisch löscht (siehe tp_clear).

  • Wenn Python ein Objekt automatisch löschen wird (siehe tp_clear), wird es das Objekt zuerst automatisch finalisieren.

Python finalisiert derzeit nur Objekte, die Mitglieder eines zyklischen Isolats sind, aber zukünftige Versionen könnten Objekte regelmäßig vor ihrer Zerstörung finalisieren.

Um ein Objekt manuell zu finalisieren, rufen Sie diese Funktion nicht direkt auf; rufen Sie stattdessen PyObject_CallFinalizer() oder PyObject_CallFinalizerFromDealloc() auf.

tp_finalize sollte den aktuellen Ausnahmezustand unverändert lassen. Die empfohlene Methode, einen nicht trivialen Finalizer zu schreiben, besteht darin, die Ausnahme am Anfang zu sichern, indem PyErr_GetRaisedException() aufgerufen wird, und die Ausnahme am Ende wiederherzustellen, indem PyErr_SetRaisedException() aufgerufen wird. Wenn während der Ausführung des Finalizers eine Ausnahme auftritt, sollte diese mit PyErr_WriteUnraisable() oder PyErr_FormatUnraisable() protokolliert und gelöscht werden. Zum Beispiel

static void
foo_finalize(PyObject *self)
{
    // Save the current exception, if any.
    PyObject *exc = PyErr_GetRaisedException();

    // ...

    if (do_something_that_might_raise() != success_indicator) {
        PyErr_WriteUnraisable(self);
        goto done;
    }

done:
    // Restore the saved exception.  This silently discards any exception
    // raised above, so be sure to call PyErr_WriteUnraisable first if
    // necessary.
    PyErr_SetRaisedException(exc);
}

Vererbung

Dieses Feld wird von Unterklassen vererbt.

Hinzugefügt in Version 3.4.

Geändert in Version 3.8: Vor Version 3.8 war es notwendig, das Bit Py_TPFLAGS_HAVE_FINALIZE zu setzen, damit dieses Feld verwendet werden konnte. Dies ist nicht mehr erforderlich.

Siehe auch

vectorcallfunc PyTypeObject.tp_vectorcall

Eine vectorcall-Funktion, die für Aufrufe dieses Typs (anstelle von Instanzen) verwendet wird. Mit anderen Worten, tp_vectorcall kann verwendet werden, um type.__call__ zu optimieren, was typischerweise eine neue Instanz von *type* zurückgibt.

Wie bei jeder vectorcall-Funktion wird, wenn tp_vectorcall NULL ist, stattdessen das *tp_call*-Protokoll (Py_TYPE(type)->tp_call) verwendet.

Hinweis

Das vectorcall-Protokoll erfordert, dass die vectorcall-Funktion das gleiche Verhalten wie die entsprechende tp_call aufweist. Dies bedeutet, dass type->tp_vectorcall mit dem Verhalten von Py_TYPE(type)->tp_call übereinstimmen muss.

Speziell, wenn *type* die Standard-Metaklasse verwendet, muss type->tp_vectorcall dasselbe Verhalten aufweisen wie PyType_Type->tp_call, welche

  • ruft type->tp_new auf,

  • wenn das Ergebnis eine Unterklasse von *type* ist, ruft type->tp_init auf dem Ergebnis von tp_new auf und

  • gibt das Ergebnis von tp_new zurück.

Typischerweise wird tp_vectorcall überschrieben, um diesen Prozess für spezifische tp_new und tp_init zu optimieren. Achten Sie bei der Erstellung von für Benutzer untervererbbaren Typen darauf, dass beide überschrieben werden können (unter Verwendung von __new__() und __init__(), bzw.).

Vererbung

Dieses Feld wird nie vererbt.

Hinzugefügt in Version 3.9: (Das Feld existiert seit 3.8, wird aber erst seit 3.9 verwendet)

unsigned char PyTypeObject.tp_watched

Intern. Nicht verwenden.

Hinzugefügt in Version 3.12.

Statische Typen

Traditionell sind in C-Code definierte Typen *statisch*, d.h. eine statische PyTypeObject-Struktur wird direkt im Code definiert und mit PyType_Ready() initialisiert.

Dies führt zu Typen, die im Vergleich zu in Python definierten Typen eingeschränkt sind

  • Statische Typen sind auf eine Basis beschränkt, d.h. sie können keine Mehrfachvererbung verwenden.

  • Statische Typobjekte (aber nicht unbedingt ihre Instanzen) sind unveränderlich. Es ist nicht möglich, die Attribute des Typobjekts von Python aus hinzuzufügen oder zu ändern.

  • Statische Typobjekte werden zwischen Sub-Interpretern geteilt, daher sollten sie keinen Sub-Interpreter-spezifischen Zustand enthalten.

Da PyTypeObject als undurchsichtige Struktur nur Teil der Limited API ist, müssen alle Erweiterungsmodule, die statische Typen verwenden, für eine bestimmte Python-Nebenversion kompiliert werden.

Heap-Typen

Eine Alternative zu statischen Typen sind *heap-allokierte Typen* oder kurz *Heap-Typen*, die Klassen, die mit der class-Anweisung von Python erstellt werden, eng entsprechen. Heap-Typen haben das Flag Py_TPFLAGS_HEAPTYPE gesetzt.

Dies geschieht durch Füllen einer PyType_Spec-Struktur und Aufrufen von PyType_FromSpec(), PyType_FromSpecWithBases(), PyType_FromModuleAndSpec() oder PyType_FromMetaclass().

Zahlenobjekt-Strukturen

type PyNumberMethods

Diese Struktur enthält Zeiger auf die Funktionen, die ein Objekt zur Implementierung des Zahlenprotokolls verwendet. Jede Funktion wird von der Funktion mit ähnlichem Namen verwendet, die im Abschnitt Number Protocol dokumentiert ist.

Hier ist die Strukturdefinition

typedef struct {
     binaryfunc nb_add;
     binaryfunc nb_subtract;
     binaryfunc nb_multiply;
     binaryfunc nb_remainder;
     binaryfunc nb_divmod;
     ternaryfunc nb_power;
     unaryfunc nb_negative;
     unaryfunc nb_positive;
     unaryfunc nb_absolute;
     inquiry nb_bool;
     unaryfunc nb_invert;
     binaryfunc nb_lshift;
     binaryfunc nb_rshift;
     binaryfunc nb_and;
     binaryfunc nb_xor;
     binaryfunc nb_or;
     unaryfunc nb_int;
     void *nb_reserved;
     unaryfunc nb_float;

     binaryfunc nb_inplace_add;
     binaryfunc nb_inplace_subtract;
     binaryfunc nb_inplace_multiply;
     binaryfunc nb_inplace_remainder;
     ternaryfunc nb_inplace_power;
     binaryfunc nb_inplace_lshift;
     binaryfunc nb_inplace_rshift;
     binaryfunc nb_inplace_and;
     binaryfunc nb_inplace_xor;
     binaryfunc nb_inplace_or;

     binaryfunc nb_floor_divide;
     binaryfunc nb_true_divide;
     binaryfunc nb_inplace_floor_divide;
     binaryfunc nb_inplace_true_divide;

     unaryfunc nb_index;

     binaryfunc nb_matrix_multiply;
     binaryfunc nb_inplace_matrix_multiply;
} PyNumberMethods;

Hinweis

Binäre und ternäre Funktionen müssen den Typ aller ihrer Operanden überprüfen und die notwendigen Konvertierungen implementieren (mindestens einer der Operanden ist eine Instanz des definierten Typs). Wenn die Operation für die gegebenen Operanden nicht definiert ist, müssen binäre und ternäre Funktionen Py_NotImplemented zurückgeben. Wenn ein anderer Fehler aufgetreten ist, müssen sie NULL zurückgeben und eine Ausnahme setzen.

Hinweis

Das Feld nb_reserved sollte immer NULL sein. Es hieß früher nb_long und wurde in Python 3.0.1 umbenannt.

binaryfunc PyNumberMethods.nb_add
binaryfunc PyNumberMethods.nb_subtract
binaryfunc PyNumberMethods.nb_multiply
binaryfunc PyNumberMethods.nb_remainder
binaryfunc PyNumberMethods.nb_divmod
ternaryfunc PyNumberMethods.nb_power
unaryfunc PyNumberMethods.nb_negative
unaryfunc PyNumberMethods.nb_positive
unaryfunc PyNumberMethods.nb_absolute
inquiry PyNumberMethods.nb_bool
unaryfunc PyNumberMethods.nb_invert
binaryfunc PyNumberMethods.nb_lshift
binaryfunc PyNumberMethods.nb_rshift
binaryfunc PyNumberMethods.nb_and
binaryfunc PyNumberMethods.nb_xor
binaryfunc PyNumberMethods.nb_or
unaryfunc PyNumberMethods.nb_int
void *PyNumberMethods.nb_reserved
unaryfunc PyNumberMethods.nb_float
binaryfunc PyNumberMethods.nb_inplace_add
binaryfunc PyNumberMethods.nb_inplace_subtract
binaryfunc PyNumberMethods.nb_inplace_multiply
binaryfunc PyNumberMethods.nb_inplace_remainder
ternaryfunc PyNumberMethods.nb_inplace_power
binaryfunc PyNumberMethods.nb_inplace_lshift
binaryfunc PyNumberMethods.nb_inplace_rshift
binaryfunc PyNumberMethods.nb_inplace_and
binaryfunc PyNumberMethods.nb_inplace_xor
binaryfunc PyNumberMethods.nb_inplace_or
binaryfunc PyNumberMethods.nb_floor_divide
binaryfunc PyNumberMethods.nb_true_divide
binaryfunc PyNumberMethods.nb_inplace_floor_divide
binaryfunc PyNumberMethods.nb_inplace_true_divide
unaryfunc PyNumberMethods.nb_index
binaryfunc PyNumberMethods.nb_matrix_multiply
binaryfunc PyNumberMethods.nb_inplace_matrix_multiply

Mapping-Objekt-Strukturen

type PyMappingMethods

Diese Struktur enthält Zeiger auf die Funktionen, die ein Objekt zur Implementierung des Mapping-Protokolls verwendet. Sie hat drei Member

lenfunc PyMappingMethods.mp_length

Diese Funktion wird von PyMapping_Size() und PyObject_Size() verwendet und hat die gleiche Signatur. Dieses Feld kann auf NULL gesetzt werden, wenn das Objekt keine definierte Länge hat.

binaryfunc PyMappingMethods.mp_subscript

Diese Funktion wird von PyObject_GetItem() und PySequence_GetSlice() verwendet und hat die gleiche Signatur wie PyObject_GetItem(). Dieses Feld muss gefüllt sein, damit die Funktion PyMapping_Check() 1 zurückgibt; andernfalls kann es NULL sein.

objobjargproc PyMappingMethods.mp_ass_subscript

Diese Funktion wird von PyObject_SetItem(), PyObject_DelItem(), PySequence_SetSlice() und PySequence_DelSlice() verwendet. Sie hat die gleiche Signatur wie PyObject_SetItem(), aber *v* kann auch auf NULL gesetzt werden, um ein Element zu löschen. Wenn dieses Feld NULL ist, unterstützt das Objekt keine Elementzuweisung und -löschung.

Sequenzobjekt-Strukturen

type PySequenceMethods

Diese Struktur enthält Zeiger auf die Funktionen, die ein Objekt zur Implementierung des Sequenzprotokolls verwendet.

lenfunc PySequenceMethods.sq_length

Diese Funktion wird von PySequence_Size() und PyObject_Size() verwendet und hat die gleiche Signatur. Sie wird auch zur Behandlung negativer Indizes über die Slots sq_item und sq_ass_item verwendet.

binaryfunc PySequenceMethods.sq_concat

Diese Funktion wird von PySequence_Concat() verwendet und hat die gleiche Signatur. Sie wird auch vom Operator + verwendet, nachdem die numerische Addition über den Slot nb_add versucht wurde.

ssizeargfunc PySequenceMethods.sq_repeat

Diese Funktion wird von PySequence_Repeat() verwendet und hat die gleiche Signatur. Sie wird auch vom Operator * verwendet, nachdem die numerische Multiplikation über den Slot nb_multiply versucht wurde.

ssizeargfunc PySequenceMethods.sq_item

Diese Funktion wird von PySequence_GetItem() verwendet und hat die gleiche Signatur. Sie wird auch von PyObject_GetItem() verwendet, nachdem die Subskription über den Slot mp_subscript versucht wurde. Dieses Feld muss gefüllt sein, damit die Funktion PySequence_Check() 1 zurückgibt; andernfalls kann es NULL sein.

Negative Indizes werden wie folgt behandelt: Wenn der Slot sq_length gefüllt ist, wird er aufgerufen und die Sequenzlänge wird zur Berechnung eines positiven Index verwendet, der an sq_item übergeben wird. Wenn sq_length NULL ist, wird der Index unverändert an die Funktion übergeben.

ssizeobjargproc PySequenceMethods.sq_ass_item

Diese Funktion wird von PySequence_SetItem() verwendet und hat die gleiche Signatur. Sie wird auch von PyObject_SetItem() und PyObject_DelItem() verwendet, nachdem der Artikelzuweisungs- und Löschversuch über den mp_ass_subscript-Slot versucht wurde. Dieser Slot kann auf NULL gesetzt werden, wenn das Objekt keine Elementzuweisung und -löschung unterstützt.

objobjproc PySequenceMethods.sq_contains

Diese Funktion kann von PySequence_Contains() verwendet werden und hat die gleiche Signatur. Dieser Slot kann auf NULL gesetzt werden. In diesem Fall durchläuft PySequence_Contains() einfach die Sequenz, bis es eine Übereinstimmung findet.

binaryfunc PySequenceMethods.sq_inplace_concat

Diese Funktion wird von PySequence_InPlaceConcat() verwendet und hat die gleiche Signatur. Sie sollte ihren ersten Operanden modifizieren und ihn zurückgeben. Dieser Slot kann auf NULL gesetzt werden. In diesem Fall greift PySequence_InPlaceConcat() auf PySequence_Concat() zurück. Sie wird auch von der erweiterten Zuweisung += verwendet, nachdem sie versucht hat, eine numerische In-Place-Addition über den nb_inplace_add-Slot durchzuführen.

ssizeargfunc PySequenceMethods.sq_inplace_repeat

Diese Funktion wird von PySequence_InPlaceRepeat() verwendet und hat die gleiche Signatur. Sie sollte ihren ersten Operanden modifizieren und ihn zurückgeben. Dieser Slot kann auf NULL gesetzt werden. In diesem Fall greift PySequence_InPlaceRepeat() auf PySequence_Repeat() zurück. Sie wird auch von der erweiterten Zuweisung *= verwendet, nachdem sie versucht hat, eine numerische In-Place-Multiplikation über den nb_inplace_multiply-Slot durchzuführen.

Buffer Object Structures

type PyBufferProcs

Diese Struktur enthält Zeiger auf die Funktionen, die vom Buffer-Protokoll benötigt werden. Das Protokoll definiert, wie ein Exporteur-Objekt seine internen Daten für Konsumenten-Objekte verfügbar machen kann.

getbufferproc PyBufferProcs.bf_getbuffer

Die Signatur dieser Funktion ist

int (PyObject *exporter, Py_buffer *view, int flags);

Behandelt eine Anfrage an den Exporter, die view gemäß den flags auszufüllen. Mit Ausnahme von Punkt (3) muss eine Implementierung dieser Funktion die folgenden Schritte ausführen:

  1. Prüfen Sie, ob die Anfrage erfüllt werden kann. Wenn nicht, lösen Sie BufferError aus, setzen Sie view->obj auf NULL und geben Sie -1 zurück.

  2. Füllen Sie die angeforderten Felder aus.

  3. Inkrementieren Sie einen internen Zähler für die Anzahl der Exporte.

  4. Setzen Sie view->obj auf exporter und inkrementieren Sie view->obj.

  5. Geben Sie 0 zurück.

Wenn exporter Teil einer Kette oder eines Baums von Puffer-Anbietern ist, können zwei Hauptschemata verwendet werden:

  • Re-Export: Jedes Mitglied des Baums fungiert als Exporteur-Objekt und setzt view->obj auf eine neue Referenz auf sich selbst.

  • Weiterleitung: Die Pufferanfrage wird an das Wurzelobjekt des Baums weitergeleitet. Hier wird view->obj eine neue Referenz auf das Wurzelobjekt sein.

Die einzelnen Felder von view sind im Abschnitt Buffer-Struktur beschrieben, die Regeln, wie ein Exporteur auf spezifische Anfragen reagieren muss, sind im Abschnitt Buffer-Anfragetypen aufgeführt.

Der gesamte Speicher, auf den in der Struktur Py_buffer verwiesen wird, gehört dem Exporteur und muss gültig bleiben, solange keine Verbraucher mehr vorhanden sind. format, shape, strides, suboffsets und internal sind für den Verbraucher schreibgeschützt.

PyBuffer_FillInfo() bietet eine einfache Möglichkeit, einen einfachen Byte-Puffer bereitzustellen und dabei korrekt mit allen Anfragetypen umzugehen.

PyObject_GetBuffer() ist die Schnittstelle für den Konsumenten, die diese Funktion umschließt.

releasebufferproc PyBufferProcs.bf_releasebuffer

Die Signatur dieser Funktion ist

void (PyObject *exporter, Py_buffer *view);

Behandelt eine Anfrage zur Freigabe der Ressourcen des Puffers. Wenn keine Ressourcen freigegeben werden müssen, kann PyBufferProcs.bf_releasebuffer NULL sein. Andernfalls führt eine Standardimplementierung dieser Funktion die folgenden optionalen Schritte aus:

  1. Dekrementieren Sie einen internen Zähler für die Anzahl der Exporte.

  2. Wenn der Zähler 0 ist, geben Sie allen Speicher frei, der mit view verbunden ist.

Der Exporteur MUSS das Feld internal verwenden, um Puffer-spezifische Ressourcen zu verfolgen. Dieses Feld bleibt garantiert konstant, während ein Verbraucher eine Kopie des ursprünglichen Puffers als view-Argument übergeben KANN.

Diese Funktion darf view->obj NICHT dekrementieren, da dies automatisch in PyBuffer_Release() geschieht (dieses Schema ist nützlich zum Brechen von Referenzzyklen).

PyBuffer_Release() ist die Schnittstelle für den Konsumenten, die diese Funktion umschließt.

Async Object Structures

Hinzugefügt in Version 3.5.

type PyAsyncMethods

Diese Struktur enthält Zeiger auf die Funktionen, die zur Implementierung von awaitable und asynchronous iterator Objekten benötigt werden.

Hier ist die Strukturdefinition

typedef struct {
    unaryfunc am_await;
    unaryfunc am_aiter;
    unaryfunc am_anext;
    sendfunc am_send;
} PyAsyncMethods;
unaryfunc PyAsyncMethods.am_await

Die Signatur dieser Funktion ist

PyObject *am_await(PyObject *self);

Das zurückgegebene Objekt muss ein Iterator sein, d.h. PyIter_Check() muss 1 für dieses Objekt zurückgeben.

Dieser Slot kann auf NULL gesetzt werden, wenn ein Objekt kein awaitable ist.

unaryfunc PyAsyncMethods.am_aiter

Die Signatur dieser Funktion ist

PyObject *am_aiter(PyObject *self);

Muss ein asynchronous iterator-Objekt zurückgeben. Siehe __anext__() für Details.

Dieser Slot kann auf NULL gesetzt werden, wenn ein Objekt das Protokoll für asynchrone Iteration nicht implementiert.

unaryfunc PyAsyncMethods.am_anext

Die Signatur dieser Funktion ist

PyObject *am_anext(PyObject *self);

Muss ein awaitable-Objekt zurückgeben. Siehe __anext__() für Details. Dieser Slot kann auf NULL gesetzt werden.

sendfunc PyAsyncMethods.am_send

Die Signatur dieser Funktion ist

PySendResult am_send(PyObject *self, PyObject *arg, PyObject **result);

Siehe PyIter_Send() für Details. Dieser Slot kann auf NULL gesetzt werden.

Hinzugefügt in Version 3.10.

Slot Typ typedefs

typedef PyObject *(*allocfunc)(PyTypeObject *cls, Py_ssize_t nitems)
Teil der Stable ABI.

Der Zweck dieser Funktion ist es, die Speicherzuweisung von der Speicherinitialisierung zu trennen. Sie sollte einen Zeiger auf einen Speicherblock ausreichender Länge für die Instanz zurückgeben, ordnungsgemäß ausgerichtet und auf Null initialisiert, aber mit ob_refcnt auf 1 und ob_type auf den Typ-Argument gesetzt. Wenn die tp_itemsize des Typs ungleich Null ist, sollte das Feld ob_size des Objekts auf nitems gesetzt und die Länge des zugewiesenen Speicherblocks tp_basicsize + nitems*tp_itemsize betragen, auf ein Vielfaches von sizeof(void*) aufgerundet; andernfalls wird nitems nicht verwendet und die Länge des Blocks sollte tp_basicsize sein.

Diese Funktion sollte keine weitere Instanzinitialisierung durchführen, nicht einmal die Zuweisung von zusätzlichem Speicher; dies sollte von tp_new übernommen werden.

typedef void (*destructor)(PyObject*)
Teil der Stable ABI.
typedef void (*freefunc)(void*)

Siehe tp_free.

typedef PyObject *(*newfunc)(PyTypeObject*, PyObject*, PyObject*)
Teil der Stable ABI.

Siehe tp_new.

typedef int (*initproc)(PyObject*, PyObject*, PyObject*)
Teil der Stable ABI.

Siehe tp_init.

typedef PyObject *(*reprfunc)(PyObject*)
Teil der Stable ABI.

Siehe tp_repr.

typedef PyObject *(*getattrfunc)(PyObject *self, char *attr)
Teil der Stable ABI.

Gibt den Wert des benannten Attributs für das Objekt zurück.

typedef int (*setattrfunc)(PyObject *self, char *attr, PyObject *value)
Teil der Stable ABI.

Setzt den Wert des benannten Attributs für das Objekt. Das value-Argument wird auf NULL gesetzt, um das Attribut zu löschen.

typedef PyObject *(*getattrofunc)(PyObject *self, PyObject *attr)
Teil der Stable ABI.

Gibt den Wert des benannten Attributs für das Objekt zurück.

Siehe tp_getattro.

typedef int (*setattrofunc)(PyObject *self, PyObject *attr, PyObject *value)
Teil der Stable ABI.

Setzt den Wert des benannten Attributs für das Objekt. Das value-Argument wird auf NULL gesetzt, um das Attribut zu löschen.

Siehe tp_setattro.

typedef PyObject *(*descrgetfunc)(PyObject*, PyObject*, PyObject*)
Teil der Stable ABI.

Siehe tp_descr_get.

typedef int (*descrsetfunc)(PyObject*, PyObject*, PyObject*)
Teil der Stable ABI.

Siehe tp_descr_set.

typedef Py_hash_t (*hashfunc)(PyObject*)
Teil der Stable ABI.

Siehe tp_hash.

typedef PyObject *(*richcmpfunc)(PyObject*, PyObject*, int)
Teil der Stable ABI.

Siehe tp_richcompare.

typedef PyObject *(*getiterfunc)(PyObject*)
Teil der Stable ABI.

Siehe tp_iter.

typedef PyObject *(*iternextfunc)(PyObject*)
Teil der Stable ABI.

Siehe tp_iternext.

typedef Py_ssize_t (*lenfunc)(PyObject*)
Teil der Stable ABI.
typedef int (*getbufferproc)(PyObject*, Py_buffer*, int)
Teil der Stable ABI seit Version 3.12.
typedef void (*releasebufferproc)(PyObject*, Py_buffer*)
Teil der Stable ABI seit Version 3.12.
typedef PyObject *(*unaryfunc)(PyObject*)
Teil der Stable ABI.
typedef PyObject *(*binaryfunc)(PyObject*, PyObject*)
Teil der Stable ABI.
typedef PySendResult (*sendfunc)(PyObject*, PyObject*, PyObject*)

Siehe am_send.

typedef PyObject *(*ternaryfunc)(PyObject*, PyObject*, PyObject*)
Teil der Stable ABI.
typedef PyObject *(*ssizeargfunc)(PyObject*, Py_ssize_t)
Teil der Stable ABI.
typedef int (*ssizeobjargproc)(PyObject*, Py_ssize_t, PyObject*)
Teil der Stable ABI.
typedef int (*objobjproc)(PyObject*, PyObject*)
Teil der Stable ABI.
typedef int (*objobjargproc)(PyObject*, PyObject*, PyObject*)
Teil der Stable ABI.

Beispiele

Die folgenden sind einfache Beispiele für Python-Typdefinitionen. Sie beinhalten gängige Verwendungsmöglichkeiten, denen Sie begegnen können. Einige zeigen knifflige Grenzfälle. Für weitere Beispiele, praktische Informationen und ein Tutorial siehe Definieren von Erweiterungstypen: Tutorial und Definieren von Erweiterungstypen: Verschiedene Themen.

Ein einfacher statischer Typ

typedef struct {
    PyObject_HEAD
    const char *data;
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject),
    .tp_doc = PyDoc_STR("My objects"),
    .tp_new = myobj_new,
    .tp_dealloc = (destructor)myobj_dealloc,
    .tp_repr = (reprfunc)myobj_repr,
};

Möglicherweise finden Sie auch älteren Code (insbesondere im CPython-Codebasis) mit einem ausführlicheren Initialisierer

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    "mymod.MyObject",               /* tp_name */
    sizeof(MyObject),               /* tp_basicsize */
    0,                              /* tp_itemsize */
    (destructor)myobj_dealloc,      /* tp_dealloc */
    0,                              /* tp_vectorcall_offset */
    0,                              /* tp_getattr */
    0,                              /* tp_setattr */
    0,                              /* tp_as_async */
    (reprfunc)myobj_repr,           /* tp_repr */
    0,                              /* tp_as_number */
    0,                              /* tp_as_sequence */
    0,                              /* tp_as_mapping */
    0,                              /* tp_hash */
    0,                              /* tp_call */
    0,                              /* tp_str */
    0,                              /* tp_getattro */
    0,                              /* tp_setattro */
    0,                              /* tp_as_buffer */
    0,                              /* tp_flags */
    PyDoc_STR("My objects"),        /* tp_doc */
    0,                              /* tp_traverse */
    0,                              /* tp_clear */
    0,                              /* tp_richcompare */
    0,                              /* tp_weaklistoffset */
    0,                              /* tp_iter */
    0,                              /* tp_iternext */
    0,                              /* tp_methods */
    0,                              /* tp_members */
    0,                              /* tp_getset */
    0,                              /* tp_base */
    0,                              /* tp_dict */
    0,                              /* tp_descr_get */
    0,                              /* tp_descr_set */
    0,                              /* tp_dictoffset */
    0,                              /* tp_init */
    0,                              /* tp_alloc */
    myobj_new,                      /* tp_new */
};

Ein Typ, der schwache Referenzen, Instanz-Dicts und Hashing unterstützt

typedef struct {
    PyObject_HEAD
    const char *data;
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject),
    .tp_doc = PyDoc_STR("My objects"),
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
         Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT |
         Py_TPFLAGS_MANAGED_WEAKREF,
    .tp_new = myobj_new,
    .tp_traverse = (traverseproc)myobj_traverse,
    .tp_clear = (inquiry)myobj_clear,
    .tp_alloc = PyType_GenericNew,
    .tp_dealloc = (destructor)myobj_dealloc,
    .tp_repr = (reprfunc)myobj_repr,
    .tp_hash = (hashfunc)myobj_hash,
    .tp_richcompare = PyBaseObject_Type.tp_richcompare,
};

Eine Zeichenketten-Unterklasse, die nicht unterklassifiziert werden kann und nicht zum Erstellen von Instanzen aufgerufen werden kann (z.B. verwendet eine separate Factory-Funktion) unter Verwendung des Flags Py_TPFLAGS_DISALLOW_INSTANTIATION

typedef struct {
    PyUnicodeObject raw;
    char *extra;
} MyStr;

static PyTypeObject MyStr_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyStr",
    .tp_basicsize = sizeof(MyStr),
    .tp_base = NULL,  // set to &PyUnicode_Type in module init
    .tp_doc = PyDoc_STR("my custom str"),
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
    .tp_repr = (reprfunc)myobj_repr,
};

Der einfachste statische Typ mit Instanzen fester Länge

typedef struct {
    PyObject_HEAD
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
};

Der einfachste statische Typ mit Instanzen variabler Länge

typedef struct {
    PyObject_VAR_HEAD
    const char *data[1];
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject) - sizeof(char *),
    .tp_itemsize = sizeof(char *),
};