Typobjekt-Strukturen

Eine der wichtigsten Strukturen des Python-Objektsystems ist vielleicht die Struktur, die einen neuen Typ festlegt: die Struktur PyTypeObject. Typobjekte lassen sich mit allen PyObject_*- oder PyType_*-Funktionen behandeln, bieten den meisten Python-Anwendungen aber wenig Interessantes. Diese Objekte sind grundlegend dafür, wie Objekte sich verhalten, und deshalb für den Interpreter selbst und für jedes Erweiterungsmodul, das neue Typen umsetzt, 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, überwiegend C-Funktionszeiger, von denen jeder einen kleinen Teil der Funktionalität des Typs umsetzt. Die Felder des Typobjekts werden in diesem Abschnitt im Einzelnen untersucht. Sie werden in der Reihenfolge beschrieben, in der sie in der Struktur vorkommen.

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

Kurzübersicht

„tp-Slots“

PyTypeObject-Slot [1]

Typ

Spezialmethoden/-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

destructor

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 *

Unter-Slots

%

tp_repr

reprfunc

__repr__

X

X

X

tp_as_number

PyNumberMethods *

Unter-Slots

%

tp_as_sequence

PySequenceMethods *

Unter-Slots

%

tp_as_mapping

PyMappingMethods *

Unter-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 *

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

destructor

[tp_version_tag]

unsigned int

tp_finalize

destructor

__del__

X

tp_vectorcall

vectorcallfunc

[tp_watched]

unsigned char

Unter-Slots

Slot

Typ

Spezialmethoden

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

Parametertypen

Rückgabetyp

allocfunc

PyObject *

destructor

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

Mehr dazu steht unten unter Typedefs für Slot-Typen.

Definition von PyTypeObject

Die Strukturdefinition für PyTypeObject steht in Include/cpython/object.h. Der Bequemlichkeit halber ist sie hier 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 Struktur des Typobjekts erweitert die Struktur PyVarObject. Das Feld ob_size wird für dynamische Typen verwendet (erzeugt von type_new(), üblicherweise aus einer class-Anweisung heraus aufgerufen). Beachte, dass PyType_Type (der Metatyp) tp_itemsize initialisiert, was bedeutet, dass seine Instanzen (also Typobjekte) das Feld ob_size haben müssen.

PyObject.ob_refcnt

Der Referenzzähler des Typobjekts wird vom Makro PyObject_HEAD_INIT auf 1 initialisiert. Beachte, dass bei statisch angelegten Typobjekten die Instanzen des Typs (Objekte, deren ob_type auf den Typ zurückverweist) nicht als Referenzen zählen. Bei dynamisch angelegten Typobjekten zählen die Instanzen dagegen sehr wohl als Referenzen.

Vererbung:

Dieses Feld wird nicht an Untertypen vererbt.

PyObject.ob_type

Das ist der Typ des Typs, mit anderen Worten sein Metatyp. Er wird durch das Argument des Makros 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 allerdings, dass das kein gültiger Initialisierer sei. Deshalb ist es üblich, dem Makro PyObject_HEAD_INIT NULL zu übergeben und dieses Feld ausdrücklich am Anfang der Initialisierungsfunktion des Moduls zu setzen, bevor irgendetwas anderes geschieht. Üblicherweise sieht das so aus:

Foo_Type.ob_type = &PyType_Type;

Das sollte geschehen, bevor Instanzen des Typs erzeugt 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 an Untertypen vererbt.

PyVarObject-Slots

PyVarObject.ob_size

Bei statisch angelegten Typobjekten sollte das auf null initialisiert werden. Bei dynamisch angelegten Typobjekten hat dieses Feld eine besondere interne Bedeutung.

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

Vererbung:

Dieses Feld wird nicht an Untertypen vererbt.

PyTypeObject-Slots

Zu jedem Slot gibt es einen Abschnitt, der die Vererbung beschreibt. Kann PyType_Ready() einen Wert setzen, wenn das Feld auf NULL gesetzt ist, gibt es außerdem einen Abschnitt „Vorgabe“. (Beachte, dass viele Felder, die an PyBaseObject_Type und PyType_Type gesetzt sind, praktisch wie Vorgaben wirken.)

const char *PyTypeObject.tp_name

Die zugehörige Slot-ID steht unter Py_tp_name.

Zeiger auf eine NUL-terminierte Zeichenkette mit dem Namen des Typs. Bei Typen, die als Modulglobale zugänglich sind, sollte die Zeichenkette der vollständige Modulname sein, gefolgt von einem Punkt und dem Typnamen. Bei integrierten Typen sollte es nur der Typname sein. Ist das Modul ein Untermodul eines Pakets, gehört der vollständige Paketname zum vollständigen Modulnamen. Ein Typ namens T zum Beispiel, der im Modul M im Unterpaket Q im Paket P definiert ist, sollte den tp_name-Initialisierer "P.Q.M.T" haben.

Bei dynamisch angelegten Typobjekten sollte das nur der Typname sein. Der Modulname wird ausdrücklich im Dictionary des Typs unter dem Schlüssel '__module__' abgelegt.

Bei statisch angelegten Typobjekten sollte das Feld tp_name einen Punkt enthalten. Alles vor dem letzten Punkt wird als Attribut __module__ zugänglich gemacht, alles nach dem letzten Punkt als Attribut __name__.

Ist kein Punkt vorhanden, wird das gesamte Feld tp_name als Attribut __name__ zugänglich gemacht, und das Attribut __module__ ist undefiniert (sofern es nicht wie oben beschrieben ausdrücklich im Dictionary gesetzt wird). Das bedeutet, dass sich dein Typ nicht mit pickle serialisieren lässt. Außerdem wird er in Moduldokumentationen, die mit pydoc erzeugt werden, nicht aufgeführt.

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

Vererbung:

Dieses Feld wird nicht an Untertypen vererbt.

Py_ssize_t PyTypeObject.tp_basicsize
Py_ssize_t PyTypeObject.tp_itemsize

Über diese Felder lässt sich die Größe von Instanzen des Typs in Bytes berechnen.

Die zugehörigen Slot-IDs stehen unter Py_tp_basicsize, Py_tp_extra_basicsize und Py_tp_itemsize.

Es gibt zwei Arten von Typen: Typen mit Instanzen fester Länge haben ein Feld tp_itemsize von null, Typen mit Instanzen veränderlicher Länge ein Feld tp_itemsize ungleich null. Bei einem Typ mit Instanzen fester Länge haben alle Instanzen dieselbe Größe, die in tp_basicsize angegeben ist. (Ausnahmen von dieser Regel lassen sich mit PyUnstable_Object_GC_NewWithExtraData() machen.)

Bei einem Typ mit Instanzen veränderlicher Länge 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 legen ihn im Feld ob_size der Instanz ab. Beachte, dass das Feld ob_size später für andere Zwecke verwendet werden kann. int-Instanzen zum Beispiel nutzen die Bits von ob_size auf eine von der Implementierung festgelegte Weise. Auf den zugrunde liegenden Speicher und seine Größe sollte über PyLong_Export() zugegriffen werden.

Bemerkung

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

Umgekehrt bedeutet das Vorhandensein eines Feldes ob_size im Aufbau der Instanz nicht, dass die Instanzstruktur veränderliche Länge hat. Der Typ list zum Beispiel hat Instanzen fester Länge, und diese Instanzen haben trotzdem ein Feld ob_size. (Wie bei int solltest du ob_size von Listen nicht unmittelbar auslesen. Rufe stattdessen PyList_Size() auf.)

tp_basicsize schließt den Platz ein, der für die Daten des tp_base des Typs nötig ist, zuzüglich aller zusätzlichen Daten, die jede Instanz braucht.

Der richtige Weg, tp_basicsize zu setzen, führt über den sizeof-Operator auf der Struktur, mit der der Aufbau der Instanz deklariert wird. Diese Struktur muss die Struktur einschließen, mit der der Basistyp deklariert wird. Mit anderen Worten muss tp_basicsize größer oder gleich dem tp_basicsize des Basistyps sein.

Da jeder Typ ein Untertyp von object ist, muss diese Struktur PyObject oder PyVarObject einschließen (je nachdem, ob ob_size enthalten sein soll). Üblicherweise werden diese über das Makro PyObject_HEAD beziehungsweise PyObject_VAR_HEAD festgelegt.

Die Grundgröße schließt die Größe des GC-Kopfes nicht ein, weil dieser Kopf nicht zu PyObject_HEAD gehört.

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

Hinweise zur Ausrichtung:

  • tp_basicsize muss ein Vielfaches von _Alignof(PyObject) sein. Verwendest du wie empfohlen sizeof auf einer struct, die PyObject_HEAD einschließt, sorgt der Compiler dafür. Verwendest du keine C-struct oder Compiler-Erweiterungen wie __attribute__((packed)), liegt es an dir.

  • Erfordern die veränderlichen Elemente eine bestimmte Ausrichtung, müssen tp_basicsize und tp_itemsize jeweils ein Vielfaches dieser Ausrichtung sein. Speichert der veränderliche Teil eines Typs zum Beispiel ein double, liegt es in deiner Verantwortung, dass beide Felder ein Vielfaches von _Alignof(double) sind.

Vererbung:

Diese Felder werden von Untertypen einzeln vererbt. (Das heißt: Ist das Feld auf null gesetzt, kopiert PyType_Ready() den Wert aus dem Basistyp, was anzeigt, dass die Instanzen keinen zusätzlichen Speicher brauchen.)

Hat der Basistyp ein tp_itemsize ungleich null, ist es im Allgemeinen nicht gefahrlos möglich, tp_itemsize in einem Untertyp auf einen anderen Wert ungleich null zu setzen (das hängt allerdings von der Umsetzung des Basistyps ab).

destructor PyTypeObject.tp_dealloc

The corresponding slot ID Py_tp_dealloc is part of the Stable ABI.

Ein Zeiger auf die Destruktorfunktion der Instanz. Die Signatur der Funktion lautet:

void tp_dealloc(PyObject *self);

Die Destruktorfunktion sollte alle Referenzen entfernen, die die Instanz besitzt (also zum Beispiel Py_CLEAR() aufrufen), alle Speicherpuffer freigeben, die der Instanz gehören, und die Funktion tp_free des Typs aufrufen, um das Objekt selbst freizugeben.

Rufst du möglicherweise Funktionen auf, die den Fehlerindikator setzen können, musst du PyErr_GetRaisedException() und PyErr_SetRaisedException() verwenden, damit du einen bereits vorhandenen Fehlerindikator nicht überschreibst (die Freigabe könnte während der Behandlung eines anderen Fehlers erfolgt sein):

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

Der Dealloc-Handler selbst darf keine Ausnahme auslösen. Stößt er auf einen Fehlerfall, sollte er PyErr_FormatUnraisable() aufrufen, um eine nicht auslösbare Ausnahme zu protokollieren (und zu löschen).

Darüber, wann ein Objekt zerstört wird, werden keine Zusagen gemacht, außer:

  • Python zerstört ein Objekt sofort oder einige Zeit, nachdem die letzte Referenz darauf gelöscht wurde, sofern nicht sein Finalisierer (tp_finalize) das Objekt anschließend wieder auferstehen lässt.

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

CPython zerstört ein Objekt derzeit unmittelbar aus Py_DECREF() heraus, sobald der neue Referenzzähler null ist. Das kann sich in einer künftigen Version ändern.

Es wird empfohlen, am Anfang von tp_dealloc PyObject_CallFinalizerFromDealloc() aufzurufen, damit das Objekt vor der Zerstörung in jedem Fall finalisiert ist.

Unterstützt der Typ die Speicherbereinigung (das Flag Py_TPFLAGS_HAVE_GC ist gesetzt), sollte der Destruktor PyObject_GC_UnTrack() aufrufen, bevor er Member-Felder leert.

Es ist zulässig, tp_clear aus tp_dealloc heraus aufzurufen, um doppelten Code zu vermeiden und sicherzustellen, dass das Objekt vor der Zerstörung immer geleert ist. Sei dir bewusst, dass tp_clear bereits aufgerufen worden sein kann.

Ist der Typ auf dem Heap angelegt (Py_TPFLAGS_HEAPTYPE), sollte der Deallokator die gehaltene Referenz auf sein Typobjekt freigeben (über Py_DECREF()), nachdem er den Deallokator des Typs aufgerufen hat. Siehe den Beispielcode unten.:

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. Muss es etwas aufrufen, das eine Ausnahme auslösen könnte, ist der Ausnahmezustand zuerst zu sichern und später wiederherzustellen (nachdem etwaige 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 darf aus jedem Python-Thread aufgerufen werden, nicht nur aus dem, der das Objekt erzeugt hat (wird das Objekt Teil eines Referenzzyklus, kann dieser Zyklus von einer Speicherbereinigung in einem beliebigen Thread eingesammelt werden). Für Aufrufe der Python-API ist das kein Problem, denn der Thread, auf dem tp_dealloc aufgerufen wird, hat einen angehängten Thread-Zustand. Zerstört das zu zerstörende Objekt seinerseits Objekte aus einer anderen C-Bibliothek, ist allerdings darauf zu achten, dass das Zerstören dieser Objekte auf dem Thread, der tp_dealloc aufgerufen hat, keine Annahmen dieser Bibliothek verletzt.

Vererbung:

Dieses Feld wird an Untertypen vererbt.

Siehe auch

Object Life Cycle – Einzelheiten dazu, wie dieser Slot mit den anderen Slots zusammenhängt.

Py_ssize_t PyTypeObject.tp_vectorcall_offset

Ein wahlfreier Versatz zu einer Funktion je Instanz, die das Aufrufen des Objekts über das vectorcall-Protokoll umsetzt – eine wirksamere Alternative zum einfacheren tp_call.

Dieses Feld wird nur verwendet, wenn das Flag Py_TPFLAGS_HAVE_VECTORCALL gesetzt ist. Ist es das, muss dies eine positive ganze Zahl sein, die den Versatz eines vectorcallfunc-Zeigers in der Instanz enthält.

Der vectorcallfunc-Zeiger darf NULL sein. Die Instanz verhält sich dann so, als wäre Py_TPFLAGS_HAVE_VECTORCALL nicht gesetzt: Das Aufrufen der Instanz fällt auf tp_call zurück.

Jede Klasse, die Py_TPFLAGS_HAVE_VECTORCALL setzt, muss auch tp_call setzen und dafür sorgen, dass dessen Verhalten zur vectorcallfunc-Funktion passt. Das lässt sich erreichen, indem tp_call auf PyVectorcall_Call() gesetzt wird.

Geändert in Version 3.8: Vor Version 3.8 hieß dieser Slot tp_print. In Python 2.x diente er der Ausgabe in eine Datei. In Python 3.0 bis 3.7 war er unbenutzt.

Geändert in Version 3.12: Vor Version 3.12 war es nicht empfohlen, dass veränderliche Heap-Typen das vectorcall-Protokoll umsetzen. Setzt jemand __call__ in Python-Code, wird nur tp_call aktualisiert, womit es wahrscheinlich nicht mehr zur vectorcall-Funktion passt. Seit 3.12 schaltet das Setzen von __call__ die vectorcall-Optimierung ab, indem es das Flag Py_TPFLAGS_HAVE_VECTORCALL löscht.

Vererbung:

Dieses Feld wird immer vererbt. Das Flag Py_TPFLAGS_HAVE_VECTORCALL wird allerdings nicht immer vererbt. Ist es nicht gesetzt, verwendet die Unterklasse vectorcall nicht, außer wenn PyVectorcall_Call() ausdrücklich aufgerufen wird.

getattrfunc PyTypeObject.tp_getattr

The corresponding slot ID Py_tp_getattr is part of the Stable ABI.

Ein wahlfreier Zeiger auf die Funktion zum Lesen eines Attributs über eine Zeichenkette.

Dieses Feld ist veraltet. Ist es festgelegt, sollte es auf eine Funktion zeigen, die sich genauso verhält wie die Funktion tp_getattro, aber eine C-Zeichenkette statt eines Python-Zeichenkettenobjekts für den Attributnamen nimmt.

Vererbung:

Gruppe: tp_getattr, tp_getattro

Dieses Feld wird von Untertypen gemeinsam mit tp_getattro vererbt: Ein Untertyp erbt sowohl tp_getattr als auch tp_getattro von seinem Basistyp, wenn tp_getattr und tp_getattro des Untertyps beide NULL sind.

setattrfunc PyTypeObject.tp_setattr

The corresponding slot ID Py_tp_setattr is part of the Stable ABI.

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

Dieses Feld ist veraltet. Ist es festgelegt, sollte es auf eine Funktion zeigen, die sich genauso verhält wie die Funktion tp_setattro, aber eine C-Zeichenkette statt eines Python-Zeichenkettenobjekts für den Attributnamen nimmt.

Vererbung:

Gruppe: tp_setattr, tp_setattro

Dieses Feld wird von Untertypen gemeinsam mit tp_setattro vererbt: Ein Untertyp erbt sowohl tp_setattr als auch tp_setattro von seinem Basistyp, wenn tp_setattr und tp_setattro des Untertyps beide NULL sind.

PyAsyncMethods *PyTypeObject.tp_as_async

Zeiger auf eine zusätzliche Struktur mit Feldern, die nur für Objekte von Bedeutung sind, die die Protokolle abwartbar und asynchroner Iterator auf C-Ebene umsetzen. Einzelheiten stehen unter Strukturen für Async-Objekte.

Added in version 3.5: Früher bekannt als tp_compare und tp_reserved.

Vererbung:

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

reprfunc PyTypeObject.tp_repr

The corresponding slot ID Py_tp_repr is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion, die die integrierte Funktion repr() umsetzt.

Die Signatur ist dieselbe wie bei PyObject_Repr():

PyObject *tp_repr(PyObject *self);

Die Funktion muss eine Zeichenkette oder ein Unicode-Objekt zurückgeben. Im Idealfall sollte sie eine Zeichenkette zurückgeben, die – an eval() übergeben und in einer passenden Umgebung – ein Objekt mit demselben Wert ergibt. Ist das nicht machbar, sollte sie eine Zeichenkette zurückgeben, die mit '<' beginnt und mit '>' endet und aus der sich sowohl der Typ als auch der Wert des Objekts ableiten lassen.

Vererbung:

Dieses Feld wird an Untertypen vererbt.

Vorgabe:

Ist dieses Feld nicht gesetzt, 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 mit Feldern, die nur für Objekte von Bedeutung sind, die das Zahlenprotokoll umsetzen. Diese Felder sind unter Strukturen für Zahlenobjekte dokumentiert.

Vererbung:

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

PySequenceMethods *PyTypeObject.tp_as_sequence

Zeiger auf eine zusätzliche Struktur mit Feldern, die nur für Objekte von Bedeutung sind, die das Sequenzprotokoll umsetzen. Diese Felder sind unter Strukturen für Sequenzobjekte dokumentiert.

Vererbung:

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

PyMappingMethods *PyTypeObject.tp_as_mapping

Zeiger auf eine zusätzliche Struktur mit Feldern, die nur für Objekte von Bedeutung sind, die das Mapping-Protokoll umsetzen. Diese Felder sind unter Strukturen für Mapping-Objekte dokumentiert.

Vererbung:

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

hashfunc PyTypeObject.tp_hash

The corresponding slot ID Py_tp_hash is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion, die die integrierte Funktion hash() umsetzt.

Die Signatur ist dieselbe wie bei PyObject_Hash():

Py_hash_t tp_hash(PyObject *);

Der Wert -1 sollte nicht als gewöhnlicher Rückgabewert verwendet werden. Tritt bei der Berechnung des Hash-Werts ein Fehler auf, sollte die Funktion eine Ausnahme setzen und -1 zurückgeben.

Ist dieses Feld nicht gesetzt (und tp_richcompare ebenfalls nicht), löst der Versuch, den Hash des Objekts zu bilden, ein TypeError aus. Das entspricht dem Setzen auf PyObject_HashNotImplemented().

Dieses Feld lässt sich ausdrücklich auf PyObject_HashNotImplemented() setzen, um das Erben der hash-Methode von einem übergeordneten Typ zu unterbinden. Das wird als Entsprechung zu __hash__ = None auf Python-Ebene ausgelegt und führt dazu, dass isinstance(o, collections.Hashable) richtigerweise False zurückgibt. Beachte, dass auch die Umkehrung gilt: __hash__ = None auf Python-Ebene an einer Klasse zu setzen führt dazu, dass der Slot tp_hash auf PyObject_HashNotImplemented() gesetzt wird.

Vererbung:

Gruppe: tp_hash, tp_richcompare

Dieses Feld wird von Untertypen gemeinsam mit tp_richcompare vererbt: Ein Untertyp erbt sowohl tp_richcompare als auch tp_hash, wenn tp_richcompare und tp_hash des Untertyps beide NULL sind.

Vorgabe:

PyBaseObject_Type verwendet PyObject_GenericHash().

ternaryfunc PyTypeObject.tp_call

The corresponding slot ID Py_tp_call is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion, die das Aufrufen des Objekts umsetzt. Ist das Objekt nicht aufrufbar, sollte dies NULL sein. Die Signatur ist dieselbe wie bei PyObject_Call():

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

Vererbung:

Dieses Feld wird an Untertypen vererbt.

reprfunc PyTypeObject.tp_str

The corresponding slot ID Py_tp_str is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion, die den integrierten Vorgang str() umsetzt. (Beachte, dass str inzwischen ein Typ ist und str() den Konstruktor dieses Typs 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 bei PyObject_Str():

PyObject *tp_str(PyObject *self);

Die Funktion muss eine Zeichenkette oder ein Unicode-Objekt zurückgeben. Sie sollte eine „freundliche“ Textdarstellung des Objekts sein, denn das ist die Darstellung, die unter anderem die Funktion print() verwendet.

Vererbung:

Dieses Feld wird an Untertypen vererbt.

Vorgabe:

Ist dieses Feld nicht gesetzt, wird PyObject_Repr() aufgerufen, um eine Textdarstellung zurückzugeben.

getattrofunc PyTypeObject.tp_getattro

The corresponding slot ID Py_tp_getattro is part of the Stable ABI.

Ein wahlfreier Zeiger auf die Funktion zum Lesen eines Attributs.

Die Signatur ist dieselbe wie bei PyObject_GetAttr():

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

Üblicherweise ist es praktisch, dieses Feld auf PyObject_GenericGetAttr() zu setzen, was die gewöhnliche Art umsetzt, Objektattribute nachzuschlagen.

Vererbung:

Gruppe: tp_getattr, tp_getattro

Dieses Feld wird von Untertypen gemeinsam mit tp_getattr vererbt: Ein Untertyp erbt sowohl tp_getattr als auch tp_getattro von seinem Basistyp, wenn tp_getattr und tp_getattro des Untertyps beide NULL sind.

Vorgabe:

PyBaseObject_Type verwendet PyObject_GenericGetAttr().

setattrofunc PyTypeObject.tp_setattro

The corresponding slot ID Py_tp_setattro is part of the Stable ABI.

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

Die Signatur ist dieselbe wie bei PyObject_SetAttr():

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

Außerdem muss unterstützt werden, dass value auf NULL gesetzt wird, um ein Attribut zu löschen. Üblicherweise ist es praktisch, dieses Feld auf PyObject_GenericSetAttr() zu setzen, was die gewöhnliche Art umsetzt, Objektattribute zu setzen.

Vererbung:

Gruppe: tp_setattr, tp_setattro

Dieses Feld wird von Untertypen gemeinsam mit tp_setattr vererbt: Ein Untertyp erbt sowohl tp_setattr als auch tp_setattro von seinem Basistyp, wenn tp_setattr und tp_setattro des Untertyps beide NULL sind.

Vorgabe:

PyBaseObject_Type verwendet PyObject_GenericSetAttr().

PyBufferProcs *PyTypeObject.tp_as_buffer

Zeiger auf eine zusätzliche Struktur mit Feldern, die nur für Objekte von Bedeutung sind, die die Puffer-Schnittstelle umsetzen. Diese Felder sind unter Strukturen für Pufferobjekte dokumentiert.

Vererbung:

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

unsigned long PyTypeObject.tp_flags

Die zugehörige Slot-ID steht unter Py_tp_flags.

Dieses Feld ist eine Bitmaske verschiedener Flags. Manche Flags zeigen abweichendes Verhalten in bestimmten Situationen an, andere zeigen an, dass bestimmte Felder im Typobjekt (oder in den über tp_as_number, tp_as_sequence, tp_as_mapping und tp_as_buffer referenzierten Erweiterungsstrukturen), die früher nicht immer vorhanden waren, gültig sind. Ist ein solches Flag-Bit nicht gesetzt, darf auf die Typfelder, die es absichert, nicht zugegriffen werden. Sie sind stattdessen als null oder NULL zu betrachten.

Vererbung:

Die Vererbung dieses Feldes ist kompliziert. Die meisten Flag-Bits werden einzeln vererbt, das heißt: Ist ein Flag-Bit im Basistyp gesetzt, erbt der Untertyp dieses Flag-Bit. Die Flag-Bits, die Erweiterungsstrukturen betreffen, werden streng dann vererbt, wenn die Erweiterungsstruktur vererbt wird, das heißt: Der Wert des Flag-Bits im Basistyp wird zusammen mit einem Zeiger auf die Erweiterungsstruktur in den Untertyp kopiert. Das Flag-Bit Py_TPFLAGS_HAVE_GC wird gemeinsam mit den Feldern tp_traverse und tp_clear vererbt, also dann, wenn das Flag-Bit Py_TPFLAGS_HAVE_GC im Untertyp nicht gesetzt ist und die Felder tp_traverse und tp_clear im Untertyp vorhanden sind und NULL-Werte haben.

Vorgabe:

PyBaseObject_Type verwendet Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE.

Bitmasken:

Derzeit sind die folgenden Bitmasken festgelegt. Sie lassen sich über den Operator | miteinander verodern, um den Wert des Feldes tp_flags zu bilden. Das Makro PyType_HasFeature() nimmt einen Typ und einen Flag-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 angelegt ist, zum Beispiel bei Typen, die dynamisch über PyType_FromSpec() erzeugt werden. In diesem Fall gilt das Feld ob_type seiner Instanzen als Referenz auf den Typ, und das Typobjekt wird mit INCREF versehen, wenn eine neue Instanz erzeugt wird, und mit DECREF, wenn eine Instanz zerstört wird (das gilt nicht für Instanzen von Untertypen, sondern nur für den Typ, auf den das ob_type der Instanz verweist, bekommt INCREF oder DECREF). Heap-Typen sollten außerdem die Speicherbereinigung unterstützen, da sie mit ihrem eigenen Modulobjekt einen Referenzzyklus bilden können.

Vererbung:

???

Py_TPFLAGS_BASETYPE
Teil der Stable ABI.

Dieses Bit ist gesetzt, wenn der Typ als Basistyp eines anderen Typs verwendet werden kann. Ist dieses Bit nicht gesetzt, lässt sich vom Typ keine Unterklasse bilden (ähnlich einer „final“-Klasse in Java).

Vererbung:

???

Py_TPFLAGS_READY

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

Vererbung:

???

Py_TPFLAGS_READYING

Dieses Bit ist gesetzt, während PyType_Ready() das Typobjekt gerade initialisiert.

Vererbung:

???

Py_TPFLAGS_HAVE_GC
Teil der Stable ABI.

Dieses Bit ist gesetzt, wenn das Objekt die Speicherbereinigung unterstützt. Ist dieses Bit gesetzt, muss Speicher für neue Instanzen (siehe tp_alloc) über PyObject_GC_New oder PyType_GenericAlloc() angefordert und (siehe tp_free) über PyObject_GC_Del() freigegeben werden. Mehr dazu im Abschnitt Supporting Cyclic Garbage Collection.

Vererbung:

Gruppe: Py_TPFLAGS_HAVE_GC, tp_traverse, tp_clear

Das Flag-Bit Py_TPFLAGS_HAVE_GC wird gemeinsam mit den Feldern tp_traverse und tp_clear vererbt, also dann, wenn das Flag-Bit Py_TPFLAGS_HAVE_GC im Untertyp nicht gesetzt ist und die Felder tp_traverse und tp_clear im Untertyp vorhanden sind und NULL-Werte haben.

Py_TPFLAGS_DEFAULT
Teil der Stable ABI.

Das ist eine Bitmaske aller Bits, die das Vorhandensein bestimmter Felder im Typobjekt und seinen Erweiterungsstrukturen betreffen. Derzeit umfasst sie die folgenden Bits: Py_TPFLAGS_HAVE_STACKLESS_EXTENSION.

Vererbung:

???

Py_TPFLAGS_METHOD_DESCRIPTOR
Teil der Stable ABI seit Version 3.8.

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

Ist dieses Flag für type(meth) gesetzt, gilt:

  • meth.__get__(obj, cls)(*args, **kwds) (mit obj nicht None) muss gleichbedeutend sein mit meth(obj, *args, **kwds).

  • meth.__get__(None, cls)(*args, **kwds) muss gleichbedeutend sein mit meth(*args, **kwds).

Dieses Flag ermöglicht eine Optimierung für typische Methodenaufrufe wie obj.meth(): Es vermeidet, für obj.meth ein vorübergehendes Objekt für die „gebundene Methode“ zu erzeugen.

Added in version 3.8.

Vererbung:

Dieses Flag wird nie an Typen vererbt, bei denen das Flag Py_TPFLAGS_IMMUTABLETYPE nicht gesetzt ist. Bei Erweiterungstypen wird es immer dann 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 die VM den Platz für das Dictionary verwaltet.

Ist dieses Flag gesetzt, muss auch Py_TPFLAGS_HAVE_GC gesetzt sein.

Die traverse-Funktion des Typs muss PyObject_VisitManagedDict() aufrufen und seine clear-Funktion PyObject_ClearManagedDict().

Added in version 3.12.

Vererbung:

Dieses Flag wird vererbt, sofern das Feld tp_dictoffset nicht in einer Oberklasse gesetzt ist.

Py_TPFLAGS_MANAGED_WEAKREF

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

Ist dieses Flag gesetzt, muss auch Py_TPFLAGS_HAVE_GC gesetzt sein.

Added in version 3.12.

Vererbung:

Dieses Flag wird vererbt, sofern das Feld tp_weaklistoffset nicht in einer Oberklasse gesetzt ist.

Py_TPFLAGS_PREHEADER

Diese Bits zeigen an, dass die VM einige Felder verwaltet, indem sie sie vor dem Objekt ablegt. Derzeit entspricht dieses Makro Py_TPFLAGS_MANAGED_DICT | Py_TPFLAGS_MANAGED_WEAKREF.

Der Wert dieses Makros hängt von der Umsetzung der VM ab, er ist deshalb nicht stabil und kann sich in einer künftigen Version ändern. Verwende besser die einzelnen Flags.

Added in version 3.12.

Py_TPFLAGS_ITEMS_AT_END
Teil der Stable ABI seit Version 3.12.

Nur bei Typen veränderlicher Größe verwendbar, also solchen mit einem tp_itemsize ungleich null.

Zeigt an, dass der Teil veränderlicher Größe einer Instanz dieses Typs am Ende des Speicherbereichs der Instanz liegt, beim Versatz Py_TYPE(obj)->tp_basicsize (der in jeder Unterklasse anders sein kann).

Vergewissere dich beim Setzen dieses Flags, dass alle Oberklassen entweder denselben Speicheraufbau verwenden oder nicht von veränderlicher Größe sind. Python prüft das nicht.

Added 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

Funktionen wie PyLong_Check() rufen PyType_FastSubclass() mit einem dieser Flags auf, um schnell festzustellen, ob ein Typ eine Unterklasse eines integrierten Typs ist. Solche gezielten Prüfungen sind schneller als eine allgemeine Prüfung wie PyObject_IsInstance(). Bei eigenen Typen, die von integrierten Typen erben, sollte tp_flags passend gesetzt sein, sonst verhält sich der Code, der mit solchen Typen umgeht, je nach verwendeter Prüfung unterschiedlich.

Py_TPFLAGS_HAVE_FINALIZE

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

Added in version 3.4.

Veraltet ab Version 3.8: Dieses Flag ist nicht mehr nötig, weil der Interpreter davon ausgeht, dass der Slot tp_finalize in der Typstruktur immer vorhanden ist.

Py_TPFLAGS_HAVE_VECTORCALL
Teil der Stable ABI seit Version 3.12.

Dieses Bit ist gesetzt, wenn die Klasse das vectorcall-Protokoll umsetzt. Einzelheiten stehen unter tp_vectorcall_offset.

Vererbung:

Dieses Bit wird vererbt, wenn auch tp_call vererbt wird.

Added in version 3.8: als _Py_TPFLAGS_HAVE_VECTORCALL

Geändert in Version 3.9: Auf den jetzigen Namen umbenannt, ohne den führenden Unterstrich. Der alte vorläufige Name ist sanft abgekündigt.

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

Dieses Flag kann jetzt von veränderlichen Klassen geerbt werden.

Py_TPFLAGS_IMMUTABLETYPE

Dieses Bit ist bei Typobjekten gesetzt, die unveränderlich sind: Typattribute lassen sich weder setzen noch löschen.

PyType_Ready() setzt dieses Flag bei statischen Typen automatisch.

Vererbung:

Dieses Flag wird nicht vererbt.

Added in version 3.10.

Py_TPFLAGS_DISALLOW_INSTANTIATION

Verbietet das Erzeugen von Instanzen des Typs: Es setzt tp_new auf NULL und legt den Schlüssel __new__ im Dictionary des Typs nicht an.

Das Flag muss gesetzt werden, bevor der Typ erzeugt wird, nicht danach. Es muss zum Beispiel gesetzt sein, bevor PyType_Ready() auf dem Typ aufgerufen wird.

Bei statischen Typen wird das Flag automatisch gesetzt, wenn tp_base NULL oder &PyBaseObject_Type ist und tp_new NULL ist.

Vererbung:

Dieses Flag wird nicht vererbt. Unterklassen lassen sich allerdings nur dann instanziieren, wenn sie ein tp_new ungleich NULL bereitstellen (was nur über die C-API möglich ist).

Bemerkung

Um das unmittelbare Instanziieren einer Klasse zu verbieten, das Instanziieren ihrer Unterklassen aber zu erlauben (etwa bei einer abstrakten Basisklasse), verwende dieses Flag nicht. Lass stattdessen tp_new nur bei Unterklassen gelingen.

Added in version 3.10.

Py_TPFLAGS_MAPPING

Dieses Bit zeigt an, dass Instanzen der Klasse auf Mapping-Muster passen können, wenn sie als Gegenstand eines match-Blocks verwendet werden. Es wird beim Registrieren oder Ableiten von collections.abc.Mapping automatisch gesetzt und beim Registrieren von collections.abc.Sequence gelöscht.

Bemerkung

Py_TPFLAGS_MAPPING und Py_TPFLAGS_SEQUENCE schließen einander aus. Beide Flags gleichzeitig einzuschalten ist ein Fehler.

Vererbung:

Dieses Flag wird an Typen vererbt, die nicht bereits Py_TPFLAGS_SEQUENCE setzen.

Siehe auch

PEP 634 – Structural Pattern Matching: Specification

Added in version 3.10.

Py_TPFLAGS_SEQUENCE

Dieses Bit zeigt an, dass Instanzen der Klasse auf Sequenzmuster passen können, wenn sie als Gegenstand eines match-Blocks verwendet werden. Es wird beim Registrieren oder Ableiten von collections.abc.Sequence automatisch gesetzt und beim Registrieren von collections.abc.Mapping gelöscht.

Bemerkung

Py_TPFLAGS_MAPPING und Py_TPFLAGS_SEQUENCE schließen einander aus. Beide Flags gleichzeitig einzuschalten ist ein Fehler.

Vererbung:

Dieses Flag wird an Typen vererbt, die nicht bereits Py_TPFLAGS_MAPPING setzen.

Siehe auch

PEP 634 – Structural Pattern Matching: Specification

Added in version 3.10.

Py_TPFLAGS_VALID_VERSION_TAG

Intern. Setze oder lösche dieses Flag nicht. Um anzuzeigen, dass eine Klasse sich geändert hat, rufe PyType_Modified() auf.

Warnung

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

Py_TPFLAGS_HAVE_VERSION_TAG

Dieses Makro tut nichts. Früher zeigte es an, dass das Feld tp_version_tag verfügbar und initialisiert war.

Py_TPFLAGS_INLINE_VALUES

Dieses Bit zeigt an, dass Instanzen dieses Typs ein Array mit „Inline-Werten“ haben (das die Attribute des Objekts enthält), das unmittelbar hinter dem Ende des Objekts liegt.

Das setzt voraus, dass Py_TPFLAGS_HAVE_GC gesetzt ist.

Vererbung:

Dieses Flag wird nicht vererbt.

Added in version 3.13.

Py_TPFLAGS_IS_ABSTRACT

Dieses Bit zeigt an, dass dies ein abstrakter Typ ist und sich deshalb nicht instanziieren lässt.

Vererbung:

Dieses Flag wird nicht vererbt.

Siehe auch

abc

Py_TPFLAGS_HAVE_STACKLESS_EXTENSION

Intern. Setze oder lösche dieses Flag nicht. Früher war das ein reserviertes Flag zur Verwendung in Stackless Python.

Warnung

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

const char *PyTypeObject.tp_doc

The corresponding slot ID Py_tp_doc is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine NUL-terminierte C-Zeichenkette mit dem Docstring für dieses Typobjekt. Er wird als Attribut __doc__ am Typ und an den Instanzen des Typs nach außen gegeben.

Vererbung:

Dieses Feld wird nicht an Untertypen vererbt.

traverseproc PyTypeObject.tp_traverse

The corresponding slot ID Py_tp_traverse is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine traverse-Funktion für die Speicherbereinigung. Sie wird nur verwendet, wenn das Flag-Bit Py_TPFLAGS_HAVE_GC gesetzt ist.

Die Dokumentation dazu steht unter Traversal.

Vererbung:

Gruppe: Py_TPFLAGS_HAVE_GC, tp_traverse, tp_clear

Dieses Feld wird von Untertypen gemeinsam 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 Untertyp alle null sind.

inquiry PyTypeObject.tp_clear

The corresponding slot ID Py_tp_clear is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine clear-Funktion. Die Signatur lautet:

int tp_clear(PyObject *);

Der Zweck dieser Funktion ist es, Referenzzyklen aufzubrechen, die ein zyklisches Isolat verursachen, damit die Objekte gefahrlos zerstört werden können. Ein geleertes Objekt ist ein teilweise zerstörtes Objekt. Es ist nicht verpflichtet, die Entwurfsinvarianten einzuhalten, die im gewöhnlichen Betrieb gelten.

tp_clear muss keine Referenzen auf Objekte löschen, die nicht an Referenzzyklen teilnehmen können, etwa Python-Zeichenketten oder ganze Zahlen. Es kann aber bequem sein, alle Referenzen zu leeren und die Funktion tp_dealloc des Typs so zu schreiben, dass sie tp_clear aufruft, um doppelten Code zu vermeiden. (Sei dir bewusst, dass tp_clear bereits aufgerufen worden sein kann. Rufe besser idempotente Funktionen wie Py_CLEAR() auf.)

Jedes nicht triviale Aufräumen sollte in tp_finalize erfolgen statt in tp_clear.

Bemerkung

Gelingt es tp_clear nicht, einen Referenzzyklus aufzubrechen, bleiben die Objekte im zyklischen Isolat möglicherweise auf Dauer nicht einsammelbar („Leck“). Siehe gc.garbage.

Bemerkung

Referenzierte Objekte (unmittelbar und mittelbar) können bereits geleert worden sein. Dass sie in einem widerspruchsfreien Zustand sind, ist nicht zugesichert.

Bemerkung

Die Funktion tp_clear darf aus jedem Thread aufgerufen werden.

Bemerkung

Dass ein Objekt automatisch geleert wird, bevor sein Destruktor (tp_dealloc) aufgerufen wird, ist nicht zugesichert.

Diese Funktion unterscheidet sich vom Destruktor (tp_dealloc) in folgender Hinsicht:

  • Der Zweck des Leerens eines Objekts ist es, Referenzen auf andere Objekte zu entfernen, die an einem Referenzzyklus teilnehmen könnten. Der Zweck des Destruktors ist dagegen umfassender: Er muss alle Ressourcen freigeben, die ihm gehören, auch Referenzen auf Objekte, die an keinem Referenzzyklus teilnehmen können (etwa ganze Zahlen), sowie den Speicher des Objekts selbst (durch Aufruf von tp_free).

  • Wenn tp_clear aufgerufen wird, halten andere Objekte möglicherweise noch Referenzen auf das zu leerende Objekt. Deshalb darf tp_clear den Speicher des Objekts selbst nicht freigeben (tp_free). Der Destruktor wird dagegen erst aufgerufen, wenn keine (starken) Referenzen mehr bestehen, und muss das Objekt deshalb gefahrlos zerstören, indem er es freigibt.

  • tp_clear wird möglicherweise nie automatisch aufgerufen. Der Destruktor eines Objekts wird dagegen einige Zeit, nachdem das Objekt unerreichbar geworden ist, automatisch aufgerufen (also wenn entweder keine Referenzen mehr auf das Objekt bestehen oder das Objekt Teil eines zyklischen Isolats ist).

Darüber, wann, ob und wie oft Python ein Objekt automatisch leert, werden keine Zusagen gemacht, außer:

  • Python leert ein Objekt nicht automatisch, wenn es erreichbar ist, also wenn eine Referenz darauf besteht und es nicht Teil eines zyklischen Isolats ist.

  • Python leert ein Objekt nicht automatisch, wenn es nicht automatisch finalisiert wurde (siehe tp_finalize). (Hat der Finalisierer das Objekt wieder auferstehen lassen, kann es sein, dass das Objekt vor dem Leeren noch einmal automatisch finalisiert wird oder auch nicht.)

  • Ist ein Objekt Teil eines zyklischen Isolats, leert Python es nicht automatisch, solange noch ein Mitglied des Isolats nicht automatisch finalisiert wurde (tp_finalize).

  • Python zerstört ein Objekt erst, nachdem alle automatischen Aufrufe seiner Funktion tp_clear zurückgekehrt sind. Damit ist sichergestellt, dass das Aufbrechen eines Referenzzyklus den Zeiger self nicht ungültig macht, während tp_clear noch läuft.

  • Python ruft tp_clear nicht automatisch mehrfach gleichzeitig auf.

CPython leert derzeit nur die Objekte automatisch, die nötig sind, um Referenzzyklen in einem zyklischen Isolat aufzubrechen. Künftige Versionen könnten Objekte aber regelmäßig vor ihrer Zerstörung leeren.

Zusammengenommen müssen alle Funktionen tp_clear im System gemeinsam alle Referenzzyklen aufbrechen. Das ist feinsinnig, und im Zweifel stellst du besser eine Funktion tp_clear bereit. Der Typ tuple zum Beispiel setzt keine Funktion tp_clear um, weil sich beweisen lässt, dass kein Referenzzyklus ausschließlich aus Tupeln bestehen kann. Deshalb sind die Funktionen tp_clear anderer Typen dafür zuständig, jeden Zyklus aufzubrechen, der ein Tupel enthält. Das ist nicht sofort offensichtlich, und es gibt selten einen guten Grund, tp_clear nicht umzusetzen.

Umsetzungen von tp_clear sollten die Referenzen der Instanz auf diejenigen ihrer Member fallen lassen, die Python-Objekte sein können, und ihre Zeiger auf diese Member 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, weil das Leeren von Referenzen heikel ist: Die Referenz auf das enthaltene Objekt darf erst dann freigegeben werden (über Py_DECREF()), nachdem der Zeiger auf das enthaltene Objekt auf NULL gesetzt wurde. Denn das Freigeben der Referenz kann dazu führen, dass das enthaltene Objekt zu Müll wird, was eine Kette von Aufräumvorgängen anstößt, die auch das Ausführen beliebigen Python-Codes umfassen kann (durch Finalisierer oder Weakref-Callbacks des enthaltenen Objekts). Kann solcher Code self erneut referenzieren, 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 Schritte in einer sicheren Reihenfolge aus.

Ist das Bit Py_TPFLAGS_MANAGED_DICT im Feld tp_flags gesetzt, muss die clear-Funktion PyObject_ClearManagedDict() so aufrufen:

PyObject_ClearManagedDict((PyObject*)self);

Mehr Informationen zum Verfahren der Speicherbereinigung in Python stehen im Abschnitt Supporting Cyclic Garbage Collection.

Vererbung:

Gruppe: Py_TPFLAGS_HAVE_GC, tp_traverse, tp_clear

Dieses Feld wird von Untertypen gemeinsam mit tp_traverse 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 Untertyp alle null sind.

Siehe auch

Object Life Cycle – Einzelheiten dazu, wie dieser Slot mit den anderen Slots zusammenhängt.

richcmpfunc PyTypeObject.tp_richcompare

The corresponding slot ID Py_tp_richcompare is part of the Stable ABI.

Ein wahlfreier Zeiger auf die Funktion für den erweiterten Vergleich, deren Signatur lautet:

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

Der erste Parameter ist garantiert eine Instanz des Typs, der durch PyTypeObject festgelegt ist.

Die Funktion sollte das Ergebnis des Vergleichs zurückgeben (üblicherweise Py_True oder Py_False). Ist der Vergleich undefiniert, muss sie Py_NotImplemented zurückgeben. Trat ein anderer Fehler auf, muss sie NULL zurückgeben und einen Ausnahmezustand setzen.

Die folgenden Konstanten sind festgelegt, um als drittes 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 festgelegt, um das Schreiben von Funktionen für den erweiterten Vergleich zu erleichtern:

Py_RETURN_RICHCOMPARE(VAL_A, VAL_B, op)

Gibt je nach Ergebnis eines Vergleichs Py_True oder Py_False aus der Funktion zurück. VAL_A und VAL_B müssen sich über die C-Vergleichsoperatoren ordnen lassen (sie dürfen zum Beispiel C-ints oder -floats sein). Das dritte Argument gibt den gewünschten Vorgang an, wie bei PyObject_RichCompare().

Der zurückgegebene Wert ist eine neue starke Referenz.

Im Fehlerfall setzt es eine Ausnahme und gibt NULL aus der Funktion zurück.

Added in version 3.7.

Vererbung:

Gruppe: tp_hash, tp_richcompare

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

Vorgabe:

PyBaseObject_Type stellt eine Umsetzung von tp_richcompare bereit, die geerbt werden kann. Ist allerdings nur tp_hash festgelegt, wird nicht einmal die geerbte Funktion verwendet, und Instanzen des Typs können an keinerlei Vergleichen teilnehmen.

Py_ssize_t PyTypeObject.tp_weaklistoffset

Dieses Feld wird zwar weiterhin unterstützt, aber nach Möglichkeit sollte stattdessen Py_TPFLAGS_MANAGED_WEAKREF verwendet werden.

Sind die Instanzen dieses Typs schwach referenzierbar, ist dieses Feld größer als null und enthält den Versatz des Kopfes der Liste schwacher Referenzen in der Instanzstruktur (ohne den GC-Kopf, falls vorhanden). Dieser Versatz wird von PyObject_ClearWeakRefs() und den PyWeakref_*-Funktionen verwendet. Die Instanzstruktur muss ein Feld vom Typ PyObject* enthalten, das auf NULL initialisiert wird.

Verwechsle dieses Feld nicht mit tp_weaklist. Das ist der Listenkopf 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 an Untertypen vererbt, siehe aber die unten aufgeführten Regeln. Ein Untertyp darf diesen Versatz übergehen. Das bedeutet, dass der Untertyp einen anderen Kopf der Liste schwacher Referenzen verwendet als der Basistyp. Da der Listenkopf immer über tp_weaklistoffset gefunden wird, sollte das kein Problem sein.

Vorgabe:

Ist das Bit Py_TPFLAGS_MANAGED_WEAKREF im Feld tp_flags gesetzt, wird tp_weaklistoffset auf einen negativen Wert gesetzt, um anzuzeigen, dass es nicht gefahrlos verwendet werden kann.

getiterfunc PyTypeObject.tp_iter

The corresponding slot ID Py_tp_iter is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion, die einen Iterator für das Objekt zurückgibt. Sein Vorhandensein zeigt normalerweise an, dass die Instanzen dieses Typs iterierbar sind (Sequenzen können allerdings auch ohne diese Funktion iterierbar sein).

Diese Funktion hat dieselbe Signatur wie PyObject_GetIter():

PyObject *tp_iter(PyObject *self);

Vererbung:

Dieses Feld wird an Untertypen vererbt.

iternextfunc PyTypeObject.tp_iternext

The corresponding slot ID Py_tp_iternext is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion, die das nächste Element eines Iterators zurückgibt. Die Signatur lautet:

PyObject *tp_iternext(PyObject *self);

Ist der Iterator erschöpft, muss die Funktion tp_iternext NULL zurückgeben. Eine StopIteration-Ausnahme kann gesetzt sein oder auch nicht. Tritt ein anderer Fehler auf, muss sie ebenfalls NULL zurückgeben. Das Vorhandensein von tp_iternext zeigt an, dass die Instanzen dieses Typs Iteratoren sind.

Iteratortypen sollten außerdem die Funktion tp_iter festlegen, und diese Funktion sollte die Iterator-Instanz selbst zurückgeben (keine neue Iterator-Instanz).

Diese Funktion hat dieselbe Signatur wie PyIter_Next().

Vererbung:

Dieses Feld wird an Untertypen vererbt.

struct PyMethodDef *PyTypeObject.tp_methods

The corresponding slot ID Py_tp_methods is part of the Stable ABI.

Ein wahlfreier Zeiger auf ein statisches, NULL-terminiertes Array von PyMethodDef-Strukturen, die die gewöhnlichen Methoden dieses Typs deklarieren.

Für jeden Eintrag im Array wird dem Dictionary des Typs (siehe tp_dict unten) ein Eintrag mit einem Methodendeskriptor hinzugefügt.

Vererbung:

Dieses Feld wird nicht an Untertypen vererbt (Methoden werden über einen anderen Mechanismus vererbt).

struct PyMemberDef *PyTypeObject.tp_members

The corresponding slot ID Py_tp_members is part of the Stable ABI.

Ein wahlfreier Zeiger auf ein statisches, NULL-terminiertes Array von PyMemberDef-Strukturen, die die gewöhnlichen Datenmember (Felder oder Slots) von Instanzen dieses Typs deklarieren.

Für jeden Eintrag im Array wird dem Dictionary des Typs (siehe tp_dict unten) ein Eintrag mit einem Member-Deskriptor hinzugefügt.

Vererbung:

Dieses Feld wird nicht an Untertypen vererbt (Member werden über einen anderen Mechanismus vererbt).

struct PyGetSetDef *PyTypeObject.tp_getset

The corresponding slot ID Py_tp_getset is part of the Stable ABI.

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

Für jeden Eintrag im Array wird dem Dictionary des Typs (siehe tp_dict unten) ein Eintrag mit einem getset-Deskriptor hinzugefügt.

Vererbung:

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

PyTypeObject *PyTypeObject.tp_base

Ein wahlfreier Zeiger auf einen Basistyp, von dem Typeigenschaften geerbt werden. Auf dieser Ebene wird nur Einfachvererbung unterstützt; Mehrfachvererbung erfordert, ein Typobjekt dynamisch durch Aufruf des Metatyps zu erzeugen.

Die zugehörige Slot-ID steht unter Py_tp_base.

Bemerkung

Für das Initialisieren von Slots gelten die Regeln zum Initialisieren von Globalen. C99 verlangt, dass die Initialisierer „Adresskonstanten“ sind. Funktionsbezeichner wie PyType_GenericNew() sind mit ihrer stillschweigenden Umwandlung in einen Zeiger gültige C99-Adresskonstanten.

Der unäre Operator „&“, angewendet auf eine nicht statische Variable wie PyBaseObject_Type, muss dagegen keine Adresskonstante ergeben. Compiler dürfen das unterstützen (gcc tut es), MSVC tut es nicht. Beide Compiler halten sich in diesem Punkt streng an den Standard.

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

Vererbung:

Dieses Feld wird (selbstverständlich) nicht an Untertypen vererbt.

Vorgabe:

Dieses Feld ist auf &PyBaseObject_Type voreingestellt (was Python-Programmierer als den Typ object kennen).

PyObject *PyTypeObject.tp_dict

Das Dictionary des Typs wird hier von PyType_Ready() abgelegt.

Dieses Feld sollte normalerweise auf NULL initialisiert werden, bevor PyType_Ready aufgerufen wird. Es darf auch mit einem Dictionary mit Anfangsattributen für den Typ initialisiert werden. Sobald PyType_Ready() den Typ initialisiert hat, dürfen diesem Dictionary nur dann weitere Attribute für den Typ hinzugefügt werden, wenn sie nicht zu überladenen Operationen gehören (wie __add__()). Ist die Initialisierung des Typs abgeschlossen, sollte dieses Feld als nur lesbar behandelt werden.

Manche Typen legen ihr Dictionary nicht in diesem Slot ab. Verwende PyType_GetDict(), um das Dictionary eines beliebigen Typs zu holen.

Geändert in Version 3.12: Zu den Interna: Bei statischen integrierten Typen ist das immer NULL. Das Dictionary solcher Typen liegt stattdessen am PyInterpreterState. Verwende PyType_GetDict(), um das Dictionary eines beliebigen Typs zu bekommen.

Vererbung:

Dieses Feld wird nicht an Untertypen vererbt (die hier festgelegten Attribute werden allerdings über einen anderen Mechanismus vererbt).

Vorgabe:

Ist dieses Feld NULL, weist PyType_Ready() ihm ein neues Dictionary zu.

Warnung

Es ist nicht gefahrlos möglich, PyDict_SetItem() auf tp_dict anzuwenden oder es anderweitig über die Dictionary-C-API zu ändern.

descrgetfunc PyTypeObject.tp_descr_get

The corresponding slot ID Py_tp_descr_get is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion zum Lesen eines Deskriptors („descriptor get“).

Die Signatur der Funktion lautet:

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

Vererbung:

Dieses Feld wird an Untertypen vererbt.

descrsetfunc PyTypeObject.tp_descr_set

The corresponding slot ID Py_tp_descr_set is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion zum Setzen und Löschen des Werts eines Deskriptors.

Die Signatur der Funktion lautet:

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

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

Vererbung:

Dieses Feld wird an Untertypen vererbt.

Py_ssize_t PyTypeObject.tp_dictoffset

Dieses Feld wird zwar weiterhin unterstützt, aber nach Möglichkeit sollte stattdessen Py_TPFLAGS_MANAGED_DICT verwendet werden.

Haben die Instanzen dieses Typs ein Dictionary mit Instanzvariablen, ist dieses Feld ungleich null und enthält den Versatz des Dictionarys der Instanzvariablen in den Instanzen des Typs. Dieser Versatz wird von PyObject_GenericGetAttr() verwendet.

Verwechsle dieses Feld nicht mit tp_dict. Das ist das Dictionary für die Attribute des Typobjekts selbst.

Der Wert gibt den Versatz des Dictionarys vom Anfang der Instanzstruktur an.

tp_dictoffset sollte als nur schreibbar betrachtet werden. Um den Zeiger auf das Dictionary zu bekommen, rufe PyObject_GenericGetDict() auf. Der Aufruf von PyObject_GenericGetDict() muss möglicherweise Speicher für das Dictionary anfordern, deshalb kann es wirksamer sein, PyObject_GetAttr() aufzurufen, wenn du auf ein Attribut des Objekts zugreifst.

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

Vererbung:

Dieses Feld wird an Untertypen vererbt. Ein Untertyp sollte diesen Versatz nicht übergehen. Das könnte gefährlich sein, wenn C-Code versucht, auf das Dictionary beim bisherigen Versatz zuzugreifen. Um Vererbung richtig zu unterstützen, verwende Py_TPFLAGS_MANAGED_DICT.

Vorgabe:

Dieser Slot hat keine Vorgabe. Bei statischen Typen wird für Instanzen kein __dict__ angelegt, wenn das Feld NULL ist.

Ist das Bit Py_TPFLAGS_MANAGED_DICT im Feld tp_flags gesetzt, wird tp_dictoffset auf -1 gesetzt, um anzuzeigen, dass es nicht gefahrlos verwendet werden kann.

initproc PyTypeObject.tp_init

The corresponding slot ID Py_tp_init is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion zur Initialisierung von Instanzen.

Diese Funktion entspricht der Methode __init__() von Klassen. Wie bei __init__() lässt sich eine Instanz erzeugen, ohne __init__() aufzurufen, und eine Instanz lässt sich neu initialisieren, indem ihre Methode __init__() erneut aufgerufen wird.

Die Signatur der Funktion lautet:

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

Das Argument self ist die zu initialisierende Instanz. Die Argumente args und kwds stehen für die Positions- und Schlüsselwortargumente des Aufrufs von __init__().

Die Funktion tp_init wird, sofern sie nicht NULL ist, aufgerufen, wenn eine Instanz auf gewöhnlichem Weg durch Aufruf ihres Typs erzeugt wird, nachdem die Funktion tp_new des Typs eine Instanz des Typs zurückgegeben hat. Gibt die Funktion tp_new eine Instanz eines anderen Typs zurück, der kein Untertyp des ursprünglichen Typs ist, wird keine Funktion tp_init aufgerufen. Gibt tp_new eine Instanz eines Untertyps des ursprünglichen Typs zurück, wird tp_init des Untertyps aufgerufen.

Gibt bei Erfolg 0 zurück, im Fehlerfall -1, und setzt eine Ausnahme.

Vererbung:

Dieses Feld wird an Untertypen vererbt.

Vorgabe:

Bei statischen Typen hat dieses Feld keine Vorgabe.

allocfunc PyTypeObject.tp_alloc

The corresponding slot ID Py_tp_alloc is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion zur Speicheranforderung für Instanzen.

Die Signatur der Funktion lautet:

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

Vererbung:

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

Heap-Untertypen erben diesen Slot nicht.

Vorgabe:

Bei Heap-Untertypen ist dieses Feld immer auf PyType_GenericAlloc() gesetzt.

Bei statischen Untertypen wird dieser Slot vererbt (siehe oben).

newfunc PyTypeObject.tp_new

The corresponding slot ID Py_tp_new is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion zum Erzeugen von Instanzen.

Die Signatur der Funktion lautet:

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

Das Argument subtype ist der Typ des zu erzeugenden Objekts. Die Argumente args und kwds stehen für die Positions- und Schlüsselwortargumente des Aufrufs des Typs. Beachte, dass subtype nicht gleich dem Typ sein muss, dessen Funktion tp_new aufgerufen wird. Es darf ein Untertyp dieses Typs sein (aber kein unverwandter Typ).

Die Funktion tp_new sollte subtype->tp_alloc(subtype, nitems) aufrufen, um Platz für das Objekt anzufordern, und danach nur so viel weitere Initialisierung vornehmen, wie unbedingt nötig ist. Initialisierung, die sich gefahrlos überspringen oder wiederholen lässt, gehört in den Handler tp_init. Als Faustregel gilt: Bei unveränderlichen Typen sollte alle Initialisierung in tp_new stattfinden, bei veränderlichen Typen sollte das meiste auf tp_init verschoben werden.

Setze das Flag Py_TPFLAGS_DISALLOW_INSTANTIATION, um das Erzeugen von Instanzen des Typs in Python zu verbieten.

Vererbung:

Dieses Feld wird an Untertypen vererbt, außer an statische Typen, deren tp_base NULL oder &PyBaseObject_Type ist.

Vorgabe:

Bei statischen Typen hat dieses Feld keine Vorgabe. Das bedeutet: Ist der Slot als NULL festgelegt, lässt sich der Typ nicht aufrufen, um neue Instanzen zu erzeugen. Vermutlich gibt es dann einen anderen Weg, Instanzen zu erzeugen, etwa eine Factory-Funktion.

freefunc PyTypeObject.tp_free

The corresponding slot ID Py_tp_free is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion zur Speicherfreigabe für Instanzen. Ihre Signatur lautet:

void tp_free(void *self);

Diese Funktion muss den Speicher freigeben, den tp_alloc angefordert hat.

Vererbung:

Statische Untertypen erben diesen Slot. Er ist PyObject_Free(), wenn er von object geerbt wird. Ausnahme: Unterstützt der Typ die Speicherbereinigung (ist also das Flag Py_TPFLAGS_HAVE_GC in tp_flags gesetzt) und würde er PyObject_Free() erben, wird dieser Slot nicht vererbt, sondern ist auf PyObject_GC_Del() voreingestellt.

Heap-Untertypen erben diesen Slot nicht.

Vorgabe:

Bei Heap-Untertypen ist dieser Slot auf einen Deallokator voreingestellt, der zu PyType_GenericAlloc() und zum Wert des Flags Py_TPFLAGS_HAVE_GC passt.

Bei statischen Untertypen wird dieser Slot vererbt (siehe oben).

inquiry PyTypeObject.tp_is_gc

The corresponding slot ID Py_tp_is_gc is part of the Stable ABI.

Ein wahlfreier Zeiger auf eine Funktion, die die Speicherbereinigung aufruft.

Die Speicherbereinigung muss wissen, ob ein bestimmtes Objekt einsammelbar ist oder nicht. Normalerweise genügt es, das Feld tp_flags des Typs des Objekts anzusehen und das Flag-Bit Py_TPFLAGS_HAVE_GC zu prüfen. Manche Typen haben aber eine Mischung aus statisch und dynamisch angelegten Instanzen, und die statisch angelegten Instanzen sind nicht einsammelbar. Solche Typen sollten diese Funktion festlegen. Sie sollte 1 für eine einsammelbare und 0 für eine nicht einsammelbare Instanz zurückgeben. Die Signatur lautet:

int tp_is_gc(PyObject *self);

(Das einzige Beispiel dafür sind die Typen selbst. Der Metatyp PyType_Type legt diese Funktion fest, um zwischen statisch und dynamisch angelegten Typen zu unterscheiden.)

Vererbung:

Dieses Feld wird an Untertypen vererbt.

Vorgabe:

Dieser Slot hat keine Vorgabe. Ist dieses Feld NULL, wird Py_TPFLAGS_HAVE_GC als funktionale Entsprechung verwendet.

PyObject *PyTypeObject.tp_bases

Tupel der Basistypen.

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

Die zugehörige Slot-ID steht unter Py_tp_bases.

Warnung

Mehrfachvererbung funktioniert bei statisch festgelegten Typen nicht gut. Setzt du tp_bases auf ein Tupel, löst Python zwar keinen Fehler aus, manche Slots werden aber nur vom ersten Basistyp geerbt.

Vererbung:

Dieses Feld wird nicht vererbt.

PyObject *PyTypeObject.tp_mro

Tupel mit der aufgefalteten Menge der Basistypen, beginnend mit dem Typ selbst und endend mit object, in der Reihenfolge der Methodenauflösung.

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

Vererbung:

Dieses Feld wird nicht vererbt. Es wird von PyType_Ready() neu berechnet.

PyObject *PyTypeObject.tp_cache

Unbenutzt. Nur für den internen Gebrauch.

Vererbung:

Dieses Feld wird nicht vererbt.

void *PyTypeObject.tp_subclasses

Eine Sammlung von Unterklassen. Nur für den internen Gebrauch. Kann ein ungültiger Zeiger sein.

Um eine Liste der Unterklassen zu bekommen, rufe die Python-Methode __subclasses__() auf.

Geändert in Version 3.12: Bei manchen Typen enthält dieses Feld keinen gültigen PyObject*. Der Typ wurde zu void* geändert, um das anzuzeigen.

Vererbung:

Dieses Feld wird nicht vererbt.

PyObject *PyTypeObject.tp_weaklist

Kopf der Liste schwacher Referenzen, für schwache Referenzen auf dieses Typobjekt. Wird nicht vererbt. Nur für den internen Gebrauch.

Geändert in Version 3.12: Zu den Interna: Bei den statischen integrierten Typen ist das immer NULL, auch wenn schwache Referenzen hinzugefügt werden. Die schwachen Referenzen jedes einzelnen liegen stattdessen am PyInterpreterState. Verwende die öffentliche C-API oder das interne Makro _PyObject_GET_WEAKREFS_LISTPTR(), um dir diese Unterscheidung zu ersparen.

Vererbung:

Dieses Feld wird nicht vererbt.

destructor PyTypeObject.tp_del

The corresponding slot ID Py_tp_del is part of the Stable ABI.

Dieses Feld ist veraltet. Verwende stattdessen tp_finalize.

unsigned int PyTypeObject.tp_version_tag

Dient als Index in den Methoden-Cache. Nur für den internen Gebrauch.

Vererbung:

Dieses Feld wird nicht vererbt.

destructor PyTypeObject.tp_finalize

The corresponding slot ID Py_tp_finalize is part of the Stable ABI seit Version 3.5.

Ein wahlfreier Zeiger auf eine Funktion zur Finalisierung von Instanzen. Das ist die C-Umsetzung der speziellen Methode __del__(). Ihre Signatur lautet:

void tp_finalize(PyObject *self);

Der Hauptzweck der Finalisierung ist es, nicht triviale Aufräumarbeiten zu erledigen, die vor der Zerstörung des Objekts stattfinden müssen, solange das Objekt und alle Objekte, die es unmittelbar oder mittelbar referenziert, noch in einem widerspruchsfreien Zustand sind. Der Finalisierer darf beliebigen Python-Code ausführen.

Bevor Python ein Objekt automatisch finalisiert, können einige der unmittelbar oder mittelbar referenzierten Objekte ihrerseits bereits automatisch finalisiert worden sein. Keines der referenzierten Objekte wird zu diesem Zeitpunkt aber bereits automatisch geleert worden sein (tp_clear).

Andere, noch nicht finalisierte Objekte verwenden ein finalisiertes Objekt möglicherweise noch, deshalb muss der Finalisierer das Objekt in einem vernünftigen Zustand hinterlassen (die Invarianten müssen also weiterhin gelten).

Bemerkung

Nachdem Python ein Objekt automatisch finalisiert hat, beginnt es möglicherweise damit, das Objekt und die von ihm referenzierten Objekte (unmittelbar und mittelbar) automatisch zu leeren (tp_clear). Dass geleerte Objekte in einem widerspruchsfreien Zustand sind, ist nicht zugesichert. Ein finalisiertes Objekt muss geleerte referenzierte Objekte verkraften.

Bemerkung

Dass ein Objekt automatisch finalisiert wird, bevor sein Destruktor (tp_dealloc) aufgerufen wird, ist nicht zugesichert. Es wird empfohlen, am Anfang von tp_dealloc PyObject_CallFinalizerFromDealloc() aufzurufen, damit das Objekt vor der Zerstörung in jedem Fall finalisiert ist.

Bemerkung

Die Funktion tp_finalize darf aus jedem Thread aufgerufen werden, der GIL wird dabei allerdings gehalten.

Bemerkung

Die Funktion tp_finalize kann beim Herunterfahren aufgerufen werden, nachdem einige globale Variablen bereits gelöscht wurden. Einzelheiten stehen in der Dokumentation zur Methode __del__().

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

  1. Python markiert das Objekt möglicherweise als finalisiert. Derzeit markiert Python immer Objekte, deren Typ die Speicherbereinigung unterstützt (bei denen also das Flag Py_TPFLAGS_HAVE_GC in tp_flags gesetzt ist), und nie andere Arten von Objekten. Das kann sich in einer künftigen Version ändern.

  2. Ist das Objekt nicht als finalisiert markiert und ist seine Finalisiererfunktion tp_finalize ungleich NULL, wird die Finalisiererfunktion aufgerufen.

  3. Wurde die Finalisiererfunktion aufgerufen und hat der Finalisierer das Objekt wieder erreichbar gemacht (besteht also eine Referenz darauf und ist es nicht Teil eines zyklischen Isolats), sagt man, der Finalisierer habe das Objekt wieder auferstehen lassen. Es ist nicht festgelegt, ob der Finalisierer das Objekt auch dadurch auferstehen lassen kann, dass er eine neue Referenz darauf hinzufügt, die es nicht erreichbar macht, das Objekt also (weiterhin) Teil eines zyklischen Isolats ist.

  4. Hat der Finalisierer das Objekt wieder auferstehen lassen, wird die anstehende Zerstörung des Objekts abgebrochen, und die Markierung finalisiert wird möglicherweise entfernt, sofern vorhanden. Derzeit entfernt Python die Markierung finalisiert nie. Das kann sich in einer künftigen Version ändern.

Automatische Finalisierung bezeichnet jede Finalisierung, die Python vornimmt, außer über Aufrufe von PyObject_CallFinalizer() oder PyObject_CallFinalizerFromDealloc(). Darüber, wann, ob und wie oft ein Objekt automatisch finalisiert wird, werden keine Zusagen gemacht, außer:

  • Python finalisiert ein Objekt nicht automatisch, wenn es erreichbar ist, also wenn eine Referenz darauf besteht und es nicht Teil eines zyklischen Isolats ist.

  • Python finalisiert ein Objekt nicht automatisch, wenn das Finalisieren das Objekt nicht als finalisiert markieren würde. Derzeit trifft das auf Objekte zu, deren Typ die Speicherbereinigung nicht unterstützt, bei denen also das Flag Py_TPFLAGS_HAVE_GC nicht gesetzt ist. Solche Objekte lassen sich weiterhin von Hand finalisieren, indem PyObject_CallFinalizer() oder PyObject_CallFinalizerFromDealloc() aufgerufen wird.

  • Python finalisiert nie zwei Mitglieder eines zyklischen Isolats gleichzeitig automatisch.

  • Python finalisiert ein Objekt nicht automatisch, nachdem es das Objekt automatisch geleert hat (tp_clear).

  • Ist ein Objekt Teil eines zyklischen Isolats, finalisiert Python es nicht automatisch, nachdem es irgendein anderes Mitglied automatisch geleert hat (siehe tp_clear).

  • Python finalisiert jedes Mitglied eines zyklischen Isolats automatisch, bevor es irgendeines davon automatisch leert (siehe tp_clear).

  • Will Python ein Objekt automatisch leeren (tp_clear), finalisiert es das Objekt vorher automatisch.

CPython finalisiert derzeit nur Objekte automatisch, die Teil eines zyklischen Isolats sind. Künftige Versionen könnten Objekte aber regelmäßig vor ihrer Zerstörung finalisieren.

Um ein Objekt von Hand zu finalisieren, rufe diese Funktion nicht unmittelbar auf. Rufe stattdessen PyObject_CallFinalizer() oder PyObject_CallFinalizerFromDealloc() auf.

tp_finalize sollte den aktuellen Ausnahmezustand unverändert lassen. Der empfohlene Weg, einen nicht trivialen Finalisierer zu schreiben, ist, die Ausnahme am Anfang mit PyErr_GetRaisedException() zu sichern und am Ende mit PyErr_SetRaisedException() wiederherzustellen. Stößt du mitten im Finalisierer auf eine Ausnahme, protokolliere und lösche sie mit PyErr_WriteUnraisable() oder PyErr_FormatUnraisable(). 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 an Untertypen vererbt.

Added in version 3.4.

Geändert in Version 3.8: Vor Version 3.8 musste das Flag-Bit Py_TPFLAGS_HAVE_FINALIZE gesetzt sein, damit dieses Feld verwendet wurde. Das ist nicht mehr nötig.

Siehe auch

vectorcallfunc PyTypeObject.tp_vectorcall

The corresponding slot ID Py_tp_vectorcall is part of the Stable ABI seit Version 3.14.

Eine vectorcall-Funktion, die für Aufrufe dieses Typobjekts (nicht seiner Instanzen) verwendet wird. Mit anderen Worten lässt sich über tp_vectorcall type.__call__ optimieren, das üblicherweise 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.

Bemerkung

Das vectorcall-Protokoll verlangt, dass die vectorcall-Funktion sich genauso verhält wie das zugehörige tp_call. Das bedeutet, dass type->tp_vectorcall zum Verhalten von Py_TYPE(type)->tp_call passen muss.

Specifically, if type uses the default metaclass, type->tp_vectorcall must behave the same as Py_TYPE(type)->tp_call, which:

  • type->tp_new aufruft,

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

  • das Ergebnis von tp_new zurückgibt.

Üblicherweise wird tp_vectorcall übergangen, um diesen Ablauf für bestimmte tp_new und tp_init zu optimieren. Tust du das bei Typen, von denen Nutzer Unterklassen bilden können, beachte, dass beide übergangen werden können (über __new__() beziehungsweise __init__()).

Vererbung:

Dieses Feld wird nie vererbt.

Added in version 3.9: (das Feld gibt es seit 3.8, verwendet wird es aber erst seit 3.9)

unsigned char PyTypeObject.tp_watched

Intern. Nicht verwenden.

Added in version 3.12.

Statische Typen

Herkömmlich sind Typen, die in C-Code festgelegt werden, statisch, das heißt: Eine statische PyTypeObject-Struktur wird unmittelbar im Code festgelegt und über PyType_Ready() initialisiert.

Daraus ergeben sich Typen, die gegenüber in Python festgelegten Typen eingeschränkt sind:

  • Statische Typen sind auf einen Basistyp beschränkt, können also keine Mehrfachvererbung nutzen.

  • Statische Typobjekte (nicht unbedingt aber ihre Instanzen) sind unveränderlich. Die Attribute des Typobjekts lassen sich aus Python heraus weder hinzufügen noch ändern.

  • Statische Typobjekte werden von allen Unterinterpretern gemeinsam genutzt, sie sollten deshalb keinen Zustand enthalten, der einem einzelnen Unterinterpreter eigen ist.

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

Heap-Typen

Eine Alternative zu statischen Typen sind auf dem Heap angelegte Typen, kurz Heap-Typen, die den Klassen, die Pythons class-Anweisung erzeugt, sehr nahekommen. Bei Heap-Typen ist das Flag Py_TPFLAGS_HEAPTYPE gesetzt.

Das geschieht, indem eine PyType_Spec-Struktur gefüllt und PyType_FromSpec(), PyType_FromSpecWithBases(), PyType_FromModuleAndSpec() oder PyType_FromMetaclass() aufgerufen wird.

Strukturen für Zahlenobjekte

type PyNumberMethods

Diese Struktur enthält Zeiger auf die Funktionen, über die ein Objekt das Zahlenprotokoll umsetzt. Jede Funktion wird von der gleichnamigen Funktion verwendet, die im Abschnitt Number Protocol dokumentiert ist.

Hier 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;

Bemerkung

Binäre und ternäre Funktionen müssen den Typ all ihrer Operanden prüfen und die nötigen Umwandlungen vornehmen (mindestens einer der Operanden ist eine Instanz des festgelegten Typs). Ist der Vorgang für die gegebenen Operanden nicht festgelegt, müssen binäre und ternäre Funktionen Py_NotImplemented zurückgeben. Trat ein anderer Fehler auf, müssen sie NULL zurückgeben und eine Ausnahme setzen.

Bemerkung

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

The corresponding slot ID Py_nb_add is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_subtract

The corresponding slot ID Py_nb_subtract is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_multiply

The corresponding slot ID Py_nb_multiply is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_remainder

The corresponding slot ID Py_nb_remainder is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_divmod

The corresponding slot ID Py_nb_divmod is part of the Stable ABI.

ternaryfunc PyNumberMethods.nb_power

The corresponding slot ID Py_nb_power is part of the Stable ABI.

unaryfunc PyNumberMethods.nb_negative

The corresponding slot ID Py_nb_negative is part of the Stable ABI.

unaryfunc PyNumberMethods.nb_positive

The corresponding slot ID Py_nb_positive is part of the Stable ABI.

unaryfunc PyNumberMethods.nb_absolute

The corresponding slot ID Py_nb_absolute is part of the Stable ABI.

inquiry PyNumberMethods.nb_bool

The corresponding slot ID Py_nb_bool is part of the Stable ABI.

unaryfunc PyNumberMethods.nb_invert

The corresponding slot ID Py_nb_invert is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_lshift

The corresponding slot ID Py_nb_lshift is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_rshift

The corresponding slot ID Py_nb_rshift is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_and

The corresponding slot ID Py_nb_and is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_xor

The corresponding slot ID Py_nb_xor is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_or

The corresponding slot ID Py_nb_or is part of the Stable ABI.

unaryfunc PyNumberMethods.nb_int

The corresponding slot ID Py_nb_int is part of the Stable ABI.

void *PyNumberMethods.nb_reserved
unaryfunc PyNumberMethods.nb_float

The corresponding slot ID Py_nb_float is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_inplace_add

The corresponding slot ID Py_nb_inplace_add is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_inplace_subtract

The corresponding slot ID Py_nb_inplace_subtract is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_inplace_multiply

The corresponding slot ID Py_nb_inplace_multiply is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_inplace_remainder

The corresponding slot ID Py_nb_inplace_remainder is part of the Stable ABI.

ternaryfunc PyNumberMethods.nb_inplace_power

The corresponding slot ID Py_nb_inplace_power is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_inplace_lshift

The corresponding slot ID Py_nb_inplace_lshift is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_inplace_rshift

The corresponding slot ID Py_nb_inplace_rshift is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_inplace_and

The corresponding slot ID Py_nb_inplace_and is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_inplace_xor

The corresponding slot ID Py_nb_inplace_xor is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_inplace_or

The corresponding slot ID Py_nb_inplace_or is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_floor_divide

The corresponding slot ID Py_nb_floor_divide is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_true_divide

The corresponding slot ID Py_nb_true_divide is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_inplace_floor_divide

The corresponding slot ID Py_nb_inplace_floor_divide is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_inplace_true_divide

The corresponding slot ID Py_nb_inplace_true_divide is part of the Stable ABI.

unaryfunc PyNumberMethods.nb_index

The corresponding slot ID Py_nb_index is part of the Stable ABI.

binaryfunc PyNumberMethods.nb_matrix_multiply

The corresponding slot ID Py_nb_matrix_multiply is part of the Stable ABI seit Version 3.5.

binaryfunc PyNumberMethods.nb_inplace_matrix_multiply

The corresponding slot ID Py_nb_inplace_matrix_multiply is part of the Stable ABI seit Version 3.5.

Strukturen für Mapping-Objekte

type PyMappingMethods

Diese Struktur enthält Zeiger auf die Funktionen, über die ein Objekt das Mapping-Protokoll umsetzt. Sie hat drei Member:

lenfunc PyMappingMethods.mp_length

The corresponding slot ID Py_mp_length is part of the Stable ABI.

Diese Funktion wird von PyMapping_Size() und PyObject_Size() verwendet und hat dieselbe Signatur. Dieser Slot darf auf NULL gesetzt werden, wenn das Objekt keine festgelegte Länge hat.

binaryfunc PyMappingMethods.mp_subscript

The corresponding slot ID Py_mp_subscript is part of the Stable ABI.

Diese Funktion wird von PyObject_GetItem() und PySequence_GetSlice() verwendet und hat dieselbe Signatur wie PyObject_GetItem(). Dieser Slot muss gefüllt sein, damit die Funktion PyMapping_Check() 1 zurückgibt. Andernfalls darf er NULL sein.

objobjargproc PyMappingMethods.mp_ass_subscript

The corresponding slot ID Py_mp_ass_subscript is part of the Stable ABI.

Diese Funktion wird von PyObject_SetItem(), PyObject_DelItem(), PySequence_SetSlice() und PySequence_DelSlice() verwendet. Sie hat dieselbe Signatur wie PyObject_SetItem(), v darf aber auch auf NULL gesetzt werden, um ein Element zu löschen. Ist dieser Slot NULL, unterstützt das Objekt das Zuweisen und Löschen von Elementen nicht.

Strukturen für Sequenzobjekte

type PySequenceMethods

Diese Struktur enthält Zeiger auf die Funktionen, über die ein Objekt das Sequenzprotokoll umsetzt.

lenfunc PySequenceMethods.sq_length

The corresponding slot ID Py_sq_length is part of the Stable ABI.

Diese Funktion wird von PySequence_Size() und PyObject_Size() verwendet und hat dieselbe Signatur. Sie dient außerdem dem Umgang mit negativen Indizes über die Slots sq_item und sq_ass_item.

binaryfunc PySequenceMethods.sq_concat

The corresponding slot ID Py_sq_concat is part of the Stable ABI.

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

ssizeargfunc PySequenceMethods.sq_repeat

The corresponding slot ID Py_sq_repeat is part of the Stable ABI.

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

ssizeargfunc PySequenceMethods.sq_item

The corresponding slot ID Py_sq_item is part of the Stable ABI.

Diese Funktion wird von PySequence_GetItem() verwendet und hat dieselbe Signatur. Sie wird außerdem von PyObject_GetItem() verwendet, nachdem der Indexzugriff über den Slot mp_subscript versucht wurde. Dieser Slot muss gefüllt sein, damit die Funktion PySequence_Check() 1 zurückgibt. Andernfalls darf er NULL sein.

Mit negativen Indizes wird so umgegangen: Ist der Slot sq_length gefüllt, wird er aufgerufen, und über die Länge der Sequenz wird ein positiver Index berechnet, der an sq_item übergeben wird. Ist sq_length NULL, wird der Index unverändert an die Funktion übergeben.

ssizeobjargproc PySequenceMethods.sq_ass_item

The corresponding slot ID Py_sq_ass_item is part of the Stable ABI.

Diese Funktion wird von PySequence_SetItem() verwendet und hat dieselbe Signatur. Sie wird außerdem von PyObject_SetItem() und PyObject_DelItem() verwendet, nachdem das Zuweisen und Löschen von Elementen über den Slot mp_ass_subscript versucht wurde. Dieser Slot darf NULL bleiben, wenn das Objekt das Zuweisen und Löschen von Elementen nicht unterstützt.

objobjproc PySequenceMethods.sq_contains

The corresponding slot ID Py_sq_contains is part of the Stable ABI.

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

binaryfunc PySequenceMethods.sq_inplace_concat

The corresponding slot ID Py_sq_inplace_concat is part of the Stable ABI.

Diese Funktion wird von PySequence_InPlaceConcat() verwendet und hat dieselbe Signatur. Sie sollte ihren ersten Operanden ändern und zurückgeben. Dieser Slot darf NULL bleiben. In diesem Fall fällt PySequence_InPlaceConcat() auf PySequence_Concat() zurück. Sie wird außerdem von der erweiterten Zuweisung += verwendet, nachdem die numerische Addition an Ort und Stelle über den Slot nb_inplace_add versucht wurde.

ssizeargfunc PySequenceMethods.sq_inplace_repeat

The corresponding slot ID Py_sq_inplace_repeat is part of the Stable ABI.

Diese Funktion wird von PySequence_InPlaceRepeat() verwendet und hat dieselbe Signatur. Sie sollte ihren ersten Operanden ändern und zurückgeben. Dieser Slot darf NULL bleiben. In diesem Fall fällt PySequence_InPlaceRepeat() auf PySequence_Repeat() zurück. Sie wird außerdem von der erweiterten Zuweisung *= verwendet, nachdem die numerische Multiplikation an Ort und Stelle über den Slot nb_inplace_multiply versucht wurde.

Strukturen für Pufferobjekte

type PyBufferProcs

Diese Struktur enthält Zeiger auf die Funktionen, die das Puffer-Protokoll verlangt. Das Protokoll legt fest, wie ein exportierendes Objekt seine internen Daten für verbrauchende Objekte zugänglich machen kann.

getbufferproc PyBufferProcs.bf_getbuffer

The corresponding slot ID Py_bf_getbuffer is part of the Stable ABI seit Version 3.11.

Die Signatur dieser Funktion lautet:

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

Behandelt eine Anfrage an exporter, view so zu füllen, wie flags es angibt. Abgesehen von Punkt (3) MUSS eine Umsetzung dieser Funktion diese Schritte ausführen:

  1. Prüfen, ob die Anfrage erfüllt werden kann. Wenn nicht, BufferError auslösen, view->obj auf NULL setzen und -1 zurückgeben.

  2. Die angefragten Felder füllen.

  3. Einen internen Zähler für die Anzahl der Exporte erhöhen.

  4. view->obj auf exporter setzen und view->obj erhöhen.

  5. 0 zurückgeben.

Thread-Sicherheit:

Im Build mit freien Threads müssen Umsetzungen sicherstellen:

  • Das Erhöhen des Exportzählers in Schritt (3) ist atomar.

  • Die zugrunde liegenden Pufferdaten bleiben gültig und an einer unveränderlichen Speicherstelle, solange Exporte bestehen.

  • Bei Objekten, die sich in der Größe ändern oder neu belegen lassen (wie bytearray), wird der Exportzähler vor solchen Vorgängen atomar geprüft, und es wird BufferError ausgelöst, wenn Exporte bestehen.

  • Die Funktion lässt sich sicher gleichzeitig aus mehreren Threads aufrufen.

Siehe auch Threadsicherheit bei memoryview-Objekten zu den Zusagen zur Thread-Sicherheit von memoryview-Objekten auf Python-Ebene.

Ist exporter Teil einer Kette oder eines Baums von Pufferanbietern, sind zwei grundlegende Vorgehensweisen möglich:

  • Weiterexport: Jedes Mitglied des Baums tritt als exportierendes Objekt auf und setzt view->obj auf eine neue Referenz auf sich selbst.

  • Umleitung: Die Pufferanfrage wird an das Wurzelobjekt des Baums umgeleitet. Hier ist view->obj eine neue Referenz auf das Wurzelobjekt.

Die einzelnen Felder von view sind im Abschnitt Pufferstruktur beschrieben, die Regeln, wie ein Exporteur auf bestimmte Anfragen reagieren muss, stehen im Abschnitt Arten von Pufferanfragen.

Aller Speicher, auf den die Struktur Py_buffer zeigt, gehört dem Exporteur und muss gültig bleiben, solange noch Verbraucher vorhanden sind. format, shape, strides, suboffsets und internal sind für den Verbraucher nur lesbar.

PyBuffer_FillInfo() bietet einen einfachen Weg, einen schlichten Bytes-Puffer zugänglich zu machen und dabei alle Arten von Anfragen richtig zu behandeln.

PyObject_GetBuffer() ist die Schnittstelle für den Verbraucher, die diese Funktion umhüllt.

releasebufferproc PyBufferProcs.bf_releasebuffer

The corresponding slot ID Py_bf_releasebuffer is part of the Stable ABI seit Version 3.11.

Die Signatur dieser Funktion lautet:

void (PyObject *exporter, Py_buffer *view);

Behandelt eine Anfrage, die Ressourcen des Puffers freizugeben. Müssen keine Ressourcen freigegeben werden, darf PyBufferProcs.bf_releasebuffer NULL sein. Andernfalls führt eine gewöhnliche Umsetzung dieser Funktion diese wahlfreien Schritte aus:

  1. Einen internen Zähler für die Anzahl der Exporte verringern.

  2. Ist der Zähler 0, allen zu view gehörenden Speicher freigeben.

Thread-Sicherheit:

Im Build mit freien Threads:

  • Das Verringern des Exportzählers in Schritt (1) muss atomar sein.

  • Das Aufräumen der Ressourcen, wenn der Zähler null erreicht, muss atomar geschehen, weil die letzte Freigabe mit gleichzeitigen Freigaben anderer Threads um die Wette laufen kann und die Speicherfreigabe nur ein einziges Mal geschehen darf.

Der Exporteur MUSS das Feld internal verwenden, um pufferspezifische Ressourcen zu verfolgen. Dieses Feld bleibt zugesichert unverändert, während ein Verbraucher dem Argument view eine Kopie des ursprünglichen Puffers übergeben DARF.

Diese Funktion DARF view->obj NICHT verringern, weil das in PyBuffer_Release() automatisch geschieht (diese Vorgehensweise ist nützlich, um Referenzzyklen aufzubrechen).

PyBuffer_Release() ist die Schnittstelle für den Verbraucher, die diese Funktion umhüllt.

Strukturen für Async-Objekte

Added in version 3.5.

type PyAsyncMethods

Diese Struktur enthält Zeiger auf die Funktionen, die nötig sind, um abwartbare Objekte und asynchrone Iteratoren umzusetzen.

Hier die Strukturdefinition:

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

The corresponding slot ID Py_am_await is part of the Stable ABI seit Version 3.5.

Die Signatur dieser Funktion lautet:

PyObject *am_await(PyObject *self);

Das zurückgegebene Objekt muss ein Iterator sein, PyIter_Check() muss dafür also 1 zurückgeben.

Dieser Slot darf auf NULL gesetzt werden, wenn ein Objekt nicht abwartbar ist.

unaryfunc PyAsyncMethods.am_aiter

The corresponding slot ID Py_am_aiter is part of the Stable ABI seit Version 3.5.

Die Signatur dieser Funktion lautet:

PyObject *am_aiter(PyObject *self);

Muss ein Objekt zurückgeben, das ein asynchroner Iterator ist. Einzelheiten stehen unter __anext__().

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

unaryfunc PyAsyncMethods.am_anext

The corresponding slot ID Py_am_anext is part of the Stable ABI seit Version 3.5.

Die Signatur dieser Funktion lautet:

PyObject *am_anext(PyObject *self);

Muss ein abwartbares Objekt zurückgeben. Einzelheiten stehen unter __anext__(). Dieser Slot darf auf NULL gesetzt werden.

sendfunc PyAsyncMethods.am_send

The corresponding slot ID Py_am_send is part of the Stable ABI seit Version 3.10.

Die Signatur dieser Funktion lautet:

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

Einzelheiten stehen unter PyIter_Send(). Dieser Slot darf auf NULL gesetzt werden.

Added in version 3.10.

Typedefs für Slot-Typen

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

Diese Funktion soll die Speicherbelegung von der Speicherinitialisierung trennen. Sie sollte einen Zeiger auf einen Speicherblock zurückgeben, der für die Instanz lang genug und passend ausgerichtet und mit Nullen initialisiert ist, bei dem aber ob_refcnt auf 1 und ob_type auf das Typargument gesetzt ist. Ist tp_itemsize des Typs ungleich null, sollte das Feld ob_size des Objekts mit nitems initialisiert werden, und die Länge des belegten Speicherblocks sollte tp_basicsize + nitems*tp_itemsize sein, aufgerundet auf ein Vielfaches von sizeof(void*). Andernfalls wird nitems nicht verwendet, und die Länge des Blocks sollte tp_basicsize sein.

Diese Funktion sollte keine weitere Initialisierung der Instanz vornehmen, auch keinen zusätzlichen Speicher belegen. Das sollte tp_new erledigen.

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 des Objekts zurück.

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

Setzt den Wert des benannten Attributs des Objekts. Das Argument für den Wert 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 des Objekts zurück.

Siehe tp_getattro.

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

Setzt den Wert des benannten Attributs des Objekts. Das Argument für den Wert 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

Hier einige einfache Beispiele für Python-Typdefinitionen. Sie enthalten gängige Verwendungen, auf die du stoßen wirst. Manche zeigen knifflige Sonderfälle. Weitere Beispiele, praktische Hinweise und eine Einführung stehen unter Defining Extension Types: Tutorial und Defining Extension Types: Assorted Topics.

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,
};

Du wirst möglicherweise auch älteren Code finden (besonders in der CPython-Codebasis), der einen ausführlicheren Initialisierer verwendet:

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-Dictionaries 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_GenericAlloc,
    .tp_dealloc = (destructor)myobj_dealloc,
    .tp_repr = (reprfunc)myobj_repr,
    .tp_hash = (hashfunc)myobj_hash,
    .tp_richcompare = PyBaseObject_Type.tp_richcompare,
};

Eine str-Unterklasse, von der sich keine Unterklassen bilden lassen und die sich nicht aufrufen lässt, um Instanzen zu erzeugen (die also zum Beispiel eine eigene Fabrikfunktion verwendet), mithilfe 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 veränderlicher 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 *),
};