3. Datenmodell¶
3.1. Objekte, Werte und Typen¶
Objekte sind Pythons Abstraktion für Daten. Alle Daten in einem Python-Programm werden durch Objekte oder Beziehungen zwischen Objekten dargestellt. (In gewissem Sinne und in Übereinstimmung mit Von Neumanns Modell eines „Programmspeichers“ werden auch Codes durch Objekte repräsentiert.)
Jedes Objekt hat eine Identität, einen Typ und einen Wert. Die Identität eines Objekts ändert sich nie, nachdem es erstellt wurde; man kann sich sie als die Adresse des Objekts im Speicher vorstellen. Der Operator is vergleicht die Identität zweier Objekte; die Funktion id() gibt eine Ganzzahl zurück, die seine Identität darstellt.
CPython Implementierungsdetail: Für CPython ist id(x) die Speicheradresse, an der x gespeichert ist.
Der Typ eines Objekts bestimmt die Operationen, die das Objekt unterstützt (z. B. „hat es eine Länge?“) und definiert auch die möglichen Werte für Objekte dieses Typs. Die Funktion type() gibt den Typ eines Objekts zurück (der selbst ein Objekt ist). Wie seine Identität ist auch der Typ eines Objekts unveränderlich. [1]
Der Wert einiger Objekte kann sich ändern. Objekte, deren Wert sich ändern kann, werden als veränderlich bezeichnet; Objekte, deren Wert nach ihrer Erstellung unveränderlich ist, werden als unveränderlich bezeichnet. (Der Wert eines unveränderlichen Containerobjekts, das eine Referenz auf ein veränderliches Objekt enthält, kann sich ändern, wenn der Wert des letzteren geändert wird; das Containerobjekt wird jedoch immer noch als unveränderlich betrachtet, da die Sammlung der von ihm enthaltenen Objekte nicht geändert werden kann. Unveränderlichkeit ist also nicht streng dasselbe wie ein unveränderlicher Wert, es ist subtiler.) Die Veränderlichkeit eines Objekts wird durch seinen Typ bestimmt; zum Beispiel sind Zahlen, Zeichenketten und Tupel unveränderlich, während Dictionaries und Listen veränderlich sind.
Objekte werden niemals explizit zerstört; wenn sie jedoch unerreichbar werden, können sie vom Garbage Collector gesammelt werden. Eine Implementierung ist berechtigt, die Garbage Collection zu verzögern oder ganz wegzulassen – es ist eine Frage der Implementierungsqualität, wie die Garbage Collection implementiert wird, solange keine Objekte gesammelt werden, die noch erreichbar sind.
CPython Implementierungsdetail: CPython verwendet derzeit ein Referenzzählungsschema mit (optionaler) verzögerter Erkennung von zyklisch verknüpftem Müll, das die meisten Objekte sammelt, sobald sie unerreichbar werden, aber nicht garantiert Müll mit zyklischen Referenzen sammelt. Informationen zur Steuerung der Sammlung von zyklischem Müll finden Sie in der Dokumentation des Moduls gc. Andere Implementierungen verhalten sich anders und CPython kann sich ändern. Verlassen Sie sich nicht auf die sofortige Finalisierung von Objekten, wenn sie unerreichbar werden (daher sollten Sie Dateien immer explizit schließen).
Beachten Sie, dass die Verwendung der Tracing- oder Debugging-Einrichtungen der Implementierung Objekte am Leben erhalten kann, die normalerweise sammelbar wären. Beachten Sie auch, dass das Abfangen einer Ausnahme mit einer try…except-Anweisung Objekte am Leben erhalten kann.
Einige Objekte enthalten Referenzen auf „externe“ Ressourcen wie offene Dateien oder Fenster. Es versteht sich, dass diese Ressourcen freigegeben werden, wenn das Objekt vom Garbage Collector gesammelt wird, aber da die Garbage Collection nicht garantiert stattfindet, bieten solche Objekte auch eine explizite Möglichkeit, die externe Ressource freizugeben, normalerweise eine close()-Methode. Es wird dringend empfohlen, solche Objekte explizit zu schließen. Die try…finally-Anweisung und die with-Anweisung bieten bequeme Möglichkeiten, dies zu tun.
Einige Objekte enthalten Referenzen auf andere Objekte; diese werden als Container bezeichnet. Beispiele für Container sind Tupel, Listen und Dictionaries. Die Referenzen sind Teil des Werts eines Containers. In den meisten Fällen implizieren wir, wenn wir über den Wert eines Containers sprechen, die Werte, nicht die Identitäten der enthaltenen Objekte; wenn wir jedoch über die Veränderlichkeit eines Containers sprechen, werden nur die Identitäten der unmittelbar enthaltenen Objekte impliziert. Wenn also ein unveränderlicher Container (wie ein Tupel) eine Referenz auf ein veränderliches Objekt enthält, ändert sich sein Wert, wenn das letztere geändert wird.
Typen beeinflussen fast alle Aspekte des Objektverhaltens. Sogar die Bedeutung der Objektidentität wird in gewissem Sinne beeinflusst: für unveränderliche Typen können Operationen, die neue Werte berechnen, tatsächlich eine Referenz auf ein beliebiges vorhandenes Objekt mit demselben Typ und Wert zurückgeben, während dies bei veränderlichen Objekten nicht erlaubt ist. Zum Beispiel, nach a = 1; b = 1 können a und b je nach Implementierung auf dasselbe Objekt mit dem Wert eins verweisen oder nicht. Dies liegt daran, dass int ein unveränderlicher Typ ist, sodass die Referenz auf 1 wiederverwendet werden kann. Dieses Verhalten hängt von der verwendeten Implementierung ab und sollte daher nicht als zuverlässig betrachtet werden, aber es ist etwas, das bei der Verwendung von Objektidentitätstests zu beachten ist. Nach c = []; d = [] wird jedoch garantiert, dass c und d auf zwei verschiedene, eindeutige, neu erstellte leere Listen verweisen. (Beachten Sie, dass e = f = [] dasselbe Objekt an e und f zuweist.)
3.2. Die Standard-Typenhierarchie¶
Nachfolgend finden Sie eine Liste der in Python eingebauten Typen. Erweiterungsmodule (in C, Java oder anderen Sprachen geschrieben, je nach Implementierung) können zusätzliche Typen definieren. Zukünftige Versionen von Python können Typen zur Typenhierarchie hinzufügen (z. B. rationale Zahlen, effizient gespeicherte Arrays von Ganzzahlen usw.), obwohl solche Ergänzungen oft stattdessen über die Standardbibliothek bereitgestellt werden.
Einige der folgenden Typbeschreibungen enthalten einen Absatz mit einer Liste von „speziellen Attributen“. Dies sind Attribute, die Zugriff auf die Implementierung ermöglichen und nicht für den allgemeinen Gebrauch bestimmt sind. Ihre Definition kann sich in Zukunft ändern.
3.2.1. None¶
Dieser Typ hat einen einzigen Wert. Es gibt ein einzelnes Objekt mit diesem Wert. Dieses Objekt wird über den eingebauten Namen None aufgerufen. Es wird verwendet, um in vielen Situationen das Fehlen eines Wertes anzuzeigen, z. B. wird es von Funktionen zurückgegeben, die nichts explizit zurückgeben. Sein Wahrheitswert ist falsch.
3.2.2. NotImplemented¶
Dieser Typ hat einen einzigen Wert. Es gibt ein einzelnes Objekt mit diesem Wert. Dieses Objekt wird über den eingebauten Namen NotImplemented aufgerufen. Numerische Methoden und Rich-Comparison-Methoden sollten diesen Wert zurückgeben, wenn sie die Operation für die bereitgestellten Operanden nicht implementieren. (Der Interpreter wird dann die reflektierte Operation oder einen anderen Fallback versuchen, abhängig vom Operator.) Er sollte nicht in einem booleschen Kontext ausgewertet werden.
Weitere Details finden Sie unter Implementierung der arithmetischen Operationen.
Geändert in Version 3.9: Das Auswerten von NotImplemented in einem booleschen Kontext wurde als veraltet markiert.
Geändert in Version 3.14: Das Auswerten von NotImplemented in einem booleschen Kontext löst nun einen TypeError aus. Zuvor wurde er als True ausgewertet und gab seit Python 3.9 eine DeprecationWarning aus.
3.2.3. Ellipsis¶
Dieser Typ hat einen einzigen Wert. Es gibt ein einzelnes Objekt mit diesem Wert. Dieses Objekt wird über das Literal ... oder den eingebauten Namen Ellipsis aufgerufen. Sein Wahrheitswert ist wahr.
3.2.4. numbers.Number¶
Diese werden durch numerische Literale erstellt und als Ergebnisse von arithmetischen Operatoren und arithmetischen integrierten Funktionen zurückgegeben. Numerische Objekte sind unveränderlich; sobald sie erstellt wurden, ändert sich ihr Wert nie. Python-Zahlen sind natürlich eng mit mathematischen Zahlen verwandt, unterliegen jedoch den Einschränkungen der numerischen Darstellung in Computern.
Die String-Darstellungen der numerischen Klassen, berechnet durch __repr__() und __str__(), haben die folgenden Eigenschaften
Sie sind gültige numerische Literale, die, wenn sie an ihren Klassenkonstruktor übergeben werden, ein Objekt mit dem Wert der ursprünglichen Zahl erzeugen.
Die Darstellung erfolgt nach Möglichkeit in Basis 10.
Führende Nullen, möglicherweise mit Ausnahme einer einzelnen Null vor einem Dezimalpunkt, werden nicht angezeigt.
Nachfolgende Nullen, möglicherweise mit Ausnahme einer einzelnen Null nach einem Dezimalpunkt, werden nicht angezeigt.
Ein Vorzeichen wird nur angezeigt, wenn die Zahl negativ ist.
Python unterscheidet zwischen ganzen Zahlen, Gleitkommazahlen und komplexen Zahlen.
3.2.4.1. numbers.Integral¶
Diese repräsentieren Elemente aus der mathematischen Menge der ganzen Zahlen (positiv und negativ).
Hinweis
Die Regeln für die Ganzzahldarstellung sind so gedacht, dass sie die aussagekräftigste Interpretation von Shift- und Maskierungsoperationen mit negativen Ganzzahlen ermöglichen.
Es gibt zwei Arten von ganzen Zahlen
- Ganzzahlen (
int) Diese repräsentieren Zahlen in einem unbegrenzten Bereich, der nur durch den verfügbaren (virtuellen) Speicher begrenzt ist. Für Shift- und Maskierungsoperationen wird eine binäre Darstellung angenommen, und negative Zahlen werden in einer Variante von 2er-Komplement dargestellt, die die Illusion einer unendlichen Zeichenkette von Vorzeichenbits nach links erzeugt.
- Booleans (
bool) Diese repräsentieren die Wahrheitswerte False und True. Die beiden Objekte, die die Werte
FalseundTruerepräsentieren, sind die einzigen booleschen Objekte. Der boolesche Typ ist ein Untertyp des Ganzzahltyps, und boolesche Werte verhalten sich in fast allen Kontexten wie die Werte 0 und 1, mit der Ausnahme, dass bei der Konvertierung in eine Zeichenkette die Zeichenketten"False"bzw."True"zurückgegeben werden.
3.2.4.2. numbers.Real (float)¶
Diese repräsentieren Maschinen-Gleitkommazahlen mit doppelter Genauigkeit. Sie sind den Einschränkungen der zugrundeliegenden Maschinenarchitektur (und der C- oder Java-Implementierung) hinsichtlich des akzeptierten Bereichs und der Handhabung von Überläufen unterworfen. Python unterstützt keine Gleitkommazahlen mit einfacher Genauigkeit; die Einsparungen bei Prozessor- und Speicherverbrauch, die normalerweise der Grund für die Verwendung dieser sind, werden durch den Overhead der Verwendung von Objekten in Python überschattet, sodass es keinen Grund gibt, die Sprache mit zwei Arten von Gleitkommazahlen zu komplizieren.
3.2.4.3. numbers.Complex (complex)¶
Diese repräsentieren komplexe Zahlen als Paar von Maschinen-Gleitkommazahlen mit doppelter Genauigkeit. Die gleichen Vorbehalte gelten wie für Gleitkommazahlen. Der Real- und Imaginärteil einer komplexen Zahl z können über die schreibgeschützten Attribute z.real und z.imag abgerufen werden.
3.2.5. Sequenzen¶
Diese repräsentieren endliche geordnete Mengen, die durch nicht-negative Zahlen indiziert werden. Die eingebaute Funktion len() gibt die Anzahl der Elemente einer Sequenz zurück. Wenn die Länge einer Sequenz n ist, enthält die Indexmenge die Zahlen 0, 1, …, n-1. Das Element i der Sequenz a wird durch a[i] ausgewählt. Einige Sequenzen, einschließlich integrierter Sequenzen, interpretieren negative Indizes, indem sie die Sequenzlänge addieren. Zum Beispiel ist a[-2] gleich a[n-2], das vorletzte Element der Sequenz a mit der Länge n.
Sequenzen unterstützen auch das Slicing: a[i:j] wählt alle Elemente mit Index k aus, für die i <= k < j gilt. Wenn ein Slice als Ausdruck verwendet wird, ist er eine Sequenz desselben Typs. Der Kommentar oben zu negativen Indizes gilt auch für negative Slice-Positionen.
Einige Sequenzen unterstützen auch „erweitertes Slicing“ mit einem dritten „Step“-Parameter: a[i:j:k] wählt alle Elemente von a mit Index x aus, wobei x = i + n*k, n >= 0 und i <= x < j.
Sequenzen werden nach ihrer Veränderlichkeit unterschieden.
3.2.5.1. Unveränderliche Sequenzen¶
Ein Objekt eines unveränderlichen Sequenztyps kann nach seiner Erstellung nicht geändert werden. (Wenn das Objekt Referenzen auf andere Objekte enthält, können diese anderen Objekte veränderlich sein und geändert werden; die Sammlung von Objekten, auf die ein unveränderliches Objekt direkt verweist, kann jedoch nicht geändert werden.)
Die folgenden Typen sind unveränderliche Sequenzen
- Zeichenketten
Eine Zeichenkette ist eine Sequenz von Werten, die Unicode-Codepunkte darstellen. Alle Codepunkte im Bereich
U+0000 - U+10FFFFkönnen in einer Zeichenkette dargestellt werden. Python hat keinen char-Typ; stattdessen wird jeder Codepunkt in der Zeichenkette als Zeichenkettenobjekt der Länge1dargestellt. Die eingebaute Funktionord()konvertiert einen Codepunkt von seiner Zeichenkettenform in eine Ganzzahl im Bereich0 - 10FFFF;chr()konvertiert eine Ganzzahl im Bereich0 - 10FFFFin das entsprechende Zeichenkettenobjekt der Länge1.str.encode()kann verwendet werden, um einestrmit der angegebenen Textkodierung inbyteszu konvertieren, undbytes.decode()kann verwendet werden, um das Gegenteil zu erreichen.- Tupel
Die Elemente eines Tupels sind beliebige Python-Objekte. Tupel aus zwei oder mehr Elementen werden durch kommagetrennte Ausdrücke gebildet. Ein Tupel aus einem Element (ein „Singleton“) kann durch Anhängen eines Kommas an einen Ausdruck gebildet werden (ein Ausdruck allein erzeugt kein Tupel, da Klammern für die Gruppierung von Ausdrücken verwendbar sein müssen). Ein leeres Tupel kann durch ein leeres Klammernpaar gebildet werden.
- Bytes
Ein Bytes-Objekt ist ein unveränderliches Array. Die Elemente sind 8-Bit-Bytes, dargestellt durch Ganzzahlen im Bereich 0 <= x < 256. Bytes-Literale (wie
b'abc') und der eingebautebytes()-Konstruktor können verwendet werden, um Bytes-Objekte zu erstellen. Ebenso können Bytes-Objekte über die Methodedecode()in Zeichenketten dekodiert werden.
3.2.5.2. Veränderliche Sequenzen¶
Veränderliche Sequenzen können nach ihrer Erstellung geändert werden. Die Index- und Slicing-Schreibweisen können als Ziel von Zuweisungs- und del (Löschungs-)Anweisungen verwendet werden.
Hinweis
Die Module collections und array bieten zusätzliche Beispiele für veränderliche Sequenztypen.
Es gibt derzeit zwei integrierte veränderliche Sequenztypen
- Listen
Die Elemente einer Liste sind beliebige Python-Objekte. Listen werden durch Platzieren einer kommagetrennten Liste von Ausdrücken in eckigen Klammern gebildet. (Beachten Sie, dass keine Sonderfälle erforderlich sind, um Listen der Länge 0 oder 1 zu bilden.)
- Byte-Arrays
Ein Bytearray-Objekt ist ein veränderliches Array. Sie werden durch den eingebauten Konstruktor
bytearray()erstellt. Abgesehen davon, dass sie veränderlich (und daher nicht haschbar) sind, bieten Byte-Arrays ansonsten die gleiche Schnittstelle und Funktionalität wie unveränderlichebytes-Objekte.
3.2.6. Set-Typen¶
Diese repräsentieren ungeordnete, endliche Mengen eindeutiger, unveränderlicher Objekte. Als solche können sie durch keinen Index angesprochen werden. Sie können jedoch iteriert werden, und die eingebaute Funktion len() gibt die Anzahl der Elemente in einem Set zurück. Häufige Verwendungen für Sets sind schnelles Testen der Mitgliedschaft, Entfernen von Duplikaten aus einer Sequenz und Ausführen mathematischer Operationen wie Schnittmenge, Vereinigung, Differenz und symmetrische Differenz.
Für Set-Elemente gelten die gleichen Unveränderlichkeitsregeln wie für Dictionary-Schlüssel. Beachten Sie, dass numerische Typen den normalen Regeln für numerische Vergleiche folgen: Wenn zwei Zahlen gleich sind (z. B. 1 und 1.0), kann nur eine davon in einem Set enthalten sein.
Es gibt derzeit zwei integrierte Set-Typen
- Sets
Diese repräsentieren ein veränderliches Set. Sie werden durch den eingebauten Konstruktor
set()erstellt und können anschließend durch mehrere Methoden geändert werden, wie z. B.add.- Frozen Sets
Diese repräsentieren ein unveränderliches Set. Sie werden durch den eingebauten Konstruktor
frozenset()erstellt. Da ein Frozenset unveränderlich und hashbar ist, kann es erneut als Element eines anderen Sets oder als Dictionary-Schlüssel verwendet werden.
3.2.7. Mappings¶
Diese repräsentieren endliche Mengen von Objekten, die von beliebigen Indexmengen indiziert werden. Die Indexnotation a[k] wählt das durch k indizierte Element aus der Abbildung a aus; dies kann in Ausdrücken und als Ziel von Zuweisungen oder del-Anweisungen verwendet werden. Die eingebaute Funktion len() gibt die Anzahl der Elemente in einer Abbildung zurück.
Derzeit gibt es einen einzigen intrinsischen Abbildungstyp
3.2.7.1. Dictionaries¶
Diese stellen endliche Mengen von Objekten dar, die von nahezu beliebigen Werten indiziert werden. Die einzigen Wertetypen, die nicht als Schlüssel akzeptiert werden, sind Werte, die Listen oder Wörterbücher oder andere veränderliche Typen enthalten, die nach Wert und nicht nach Objektidentität verglichen werden. Der Grund dafür ist, dass die effiziente Implementierung von Wörterbüchern erfordert, dass der Hash-Wert eines Schlüssels konstant bleibt. Numerische Typen, die für Schlüssel verwendet werden, folgen den normalen Regeln für den numerischen Vergleich: Wenn zwei Zahlen gleich verglichen werden (z. B. 1 und 1.0), dann können sie austauschbar verwendet werden, um denselben Wörterbucheintrag zu indizieren.
Wörterbücher behalten die Einfügungsreihenfolge bei, was bedeutet, dass Schlüssel in der gleichen Reihenfolge ausgegeben werden, in der sie sequenziell in das Wörterbuch eingefügt wurden. Das Ersetzen eines vorhandenen Schlüssels ändert die Reihenfolge nicht. Das Entfernen eines Schlüssels und das erneute Einfügen fügt ihn jedoch am Ende hinzu, anstatt seinen alten Platz beizubehalten.
Wörterbücher sind veränderlich; sie können durch die Notation {} erstellt werden (siehe Abschnitt Dictionary-Anzeigen).
Die Erweiterungsmodule dbm.ndbm und dbm.gnu bieten zusätzliche Beispiele für Abbildungstypen, ebenso wie das Modul collections.
Geändert in Version 3.7: Wörterbücher behielten in Python-Versionen vor 3.6 die Einfügungsreihenfolge nicht bei. In CPython 3.6 wurde die Einfügungsreihenfolge beibehalten, aber sie galt damals als Implementierungsdetail und nicht als Sprachgarantie.
3.2.8. Aufrufbare Typen¶
Dies sind die Typen, auf die die Funktionsaufrufoperation (siehe Abschnitt Aufrufe) angewendet werden kann.
3.2.8.1. Benutzerdefinierte Funktionen¶
Ein benutzerdefiniertes Funktionsobjekt wird durch eine Funktionsdefinition erstellt (siehe Abschnitt Funktionsdefinitionen). Sie sollte mit einer Argumentliste aufgerufen werden, die die gleiche Anzahl von Elementen enthält wie die Liste der formalen Parameter der Funktion.
3.2.8.1.1. Spezielle schreibgeschützte Attribute¶
Attribut |
Bedeutung |
|---|---|
|
Eine Referenz auf das |
|
Ein Zellobjekt hat das Attribut |
3.2.8.1.2. Spezielle beschreibbare Attribute¶
Die meisten dieser Attribute prüfen den Typ des zugewiesenen Werts.
Attribut |
Bedeutung |
|---|---|
|
Der Dokumentationsstring der Funktion oder |
|
Der Name der Funktion. Siehe auch: |
|
Der qualifizierte Name der Funktion. Siehe auch: Hinzugefügt in Version 3.3. |
|
Der Name des Moduls, in dem die Funktion definiert wurde, oder |
|
Ein |
|
Das Code-Objekt, das den kompilierten Funktionskörper darstellt. |
|
Der Namensraum, der beliebige Funktionsattribute unterstützt. Siehe auch: |
|
Ein Geändert in Version 3.14: Annotationen werden jetzt lazy ausgewertet. Siehe PEP 649. |
|
Die Annotierungsfunktion für diese Funktion oder Hinzugefügt in Version 3.14. |
|
Ein |
|
Ein Hinzugefügt in Version 3.12. |
Funktionsobjekte unterstützen auch das Abrufen und Setzen beliebiger Attribute, die beispielsweise verwendet werden können, um Metadaten an Funktionen anzuhängen. Reguläre Punktnotation wird verwendet, um solche Attribute abzurufen und zu setzen.
CPython-Implementierungsdetail: Die aktuelle CPython-Implementierung unterstützt Funktionsattribute nur für benutzerdefinierte Funktionen. Funktionsattribute für eingebaute Funktionen können in Zukunft unterstützt werden.
Zusätzliche Informationen über die Definition einer Funktion können aus ihrem Code-Objekt abgerufen werden (zugänglich über das Attribut __code__).
3.2.8.2. Instanzmethoden¶
Ein Instanzmethodenobjekt kombiniert eine Klasse, eine Klasseninstanz und ein beliebiges aufrufbares Objekt (normalerweise eine benutzerdefinierte Funktion).
Spezielle schreibgeschützte Attribute
|
Verweist auf das Klasseninstanzobjekt, an das die Methode gebunden ist. |
|
Verweist auf das ursprüngliche Funktionsobjekt. |
|
Die Dokumentation der Methode (wie |
|
Der Name der Methode (wie |
|
Der Name des Moduls, in dem die Methode definiert wurde, oder |
Methoden unterstützen auch den Zugriff auf (aber nicht das Setzen von) beliebigen Funktionsattributen des zugrunde liegenden Funktionsobjekts.
Benutzerdefinierte Methodenobjekte können erstellt werden, wenn ein Attribut einer Klasse abgerufen wird (möglicherweise über eine Instanz dieser Klasse), wenn dieses Attribut ein benutzerdefiniertes Funktionsobjekt oder ein classmethod-Objekt ist.
Wenn ein Instanzmethodenobjekt durch Abrufen eines benutzerdefinierten Funktionsobjekts aus einer Klasse über eine ihrer Instanzen erstellt wird, ist sein Attribut __self__ die Instanz, und das Methodenobjekt wird als *gebunden* bezeichnet. Das Attribut __func__ der neuen Methode ist das ursprüngliche Funktionsobjekt.
Wenn ein Instanzmethodenobjekt durch Abrufen eines classmethod-Objekts von einer Klasse oder Instanz erstellt wird, ist sein Attribut __self__ die Klasse selbst und sein Attribut __func__ ist das Funktionsobjekt, das der Klassenmethode zugrunde liegt.
Wenn ein Instanzmethodenobjekt aufgerufen wird, wird die zugrunde liegende Funktion (__func__) aufgerufen, wobei die Klasseninstanz (__self__) vor der Argumentliste eingefügt wird. Wenn beispielsweise C eine Klasse ist, die eine Definition für eine Funktion f() enthält, und x eine Instanz von C ist, ist der Aufruf von x.f(1) äquivalent zu C.f(x, 1).
Wenn ein Instanzmethodenobjekt aus einem classmethod-Objekt abgeleitet wird, ist die in __self__ gespeicherte "Klasseninstanz" tatsächlich die Klasse selbst, sodass der Aufruf von x.f(1) oder C.f(1) äquivalent zu f(C,1) ist, wobei f die zugrunde liegende Funktion ist.
Es ist wichtig zu beachten, dass benutzerdefinierte Funktionen, die Attribute einer Klasseninstanz sind, nicht in gebundene Methoden umgewandelt werden; dies geschieht *nur*, wenn die Funktion ein Attribut der Klasse ist.
3.2.8.3. Generatorfunktionen¶
Eine Funktion oder Methode, die die yield-Anweisung verwendet (siehe Abschnitt Die yield-Anweisung), wird als *Generatorfunktion* bezeichnet. Eine solche Funktion gibt beim Aufruf immer ein Iterator-Objekt zurück, das verwendet werden kann, um den Körper der Funktion auszuführen: das Aufrufen der Methode iterator.__next__() führt dazu, dass die Funktion ausgeführt wird, bis sie einen Wert über die yield-Anweisung liefert. Wenn die Funktion eine return-Anweisung ausführt oder das Ende erreicht, wird eine StopIteration-Ausnahme ausgelöst und der Iterator hat das Ende der zu liefernden Werte erreicht.
3.2.8.4. Koroutinenfunktionen¶
Eine Funktion oder Methode, die mit async def definiert ist, wird als *Koroutinenfunktion* bezeichnet. Eine solche Funktion gibt beim Aufruf ein Koroutinen-Objekt zurück. Sie kann await-Ausdrücke sowie async with- und async for-Anweisungen enthalten. Siehe auch den Abschnitt Koroutinenobjekte.
3.2.8.5. Asynchrone Generatorfunktionen¶
Eine Funktion oder Methode, die mit async def definiert ist und die yield-Anweisung verwendet, wird als *asynchrone Generatorfunktion* bezeichnet. Eine solche Funktion gibt beim Aufruf ein asynchrones Iterator-Objekt zurück, das in einer async for-Anweisung verwendet werden kann, um den Körper der Funktion auszuführen.
Der Aufruf der Methode aiterator.__anext__ des asynchronen Iterators gibt ein Awaitable zurück, das beim Warten die Funktion ausführt, bis sie einen Wert über den yield-Ausdruck liefert. Wenn die Funktion eine leere return-Anweisung ausführt oder das Ende erreicht, wird eine StopAsyncIteration-Ausnahme ausgelöst und das asynchrone Iterator hat das Ende der zu liefernden Werte erreicht.
3.2.8.6. Eingebaute Funktionen¶
Ein eingebautes Funktionsobjekt ist ein Wrapper um eine C-Funktion. Beispiele für eingebaute Funktionen sind len() und math.sin() (math ist ein Standard-eingebautes Modul). Die Anzahl und Art der Argumente werden von der C-Funktion bestimmt. Spezielle schreibgeschützte Attribute
__doc__ist der Dokumentationsstring der Funktion oderNone, falls nicht verfügbar. Siehefunction.__doc__.__name__ist der Name der Funktion. Siehefunction.__name__.__self__ist aufNonegesetzt (aber siehe nächster Punkt).__module__ist der Name des Moduls, in dem die Funktion definiert wurde, oderNone, falls nicht verfügbar. Siehefunction.__module__.
3.2.8.7. Eingebaute Methoden¶
Dies ist eigentlich eine andere Erscheinungsform einer eingebauten Funktion, die diesmal ein Objekt enthält, das der C-Funktion als implizites zusätzliches Argument übergeben wird. Ein Beispiel für eine eingebaute Methode ist alist.append(), vorausgesetzt, *alist* ist ein Listenobjekt. In diesem Fall ist das spezielle schreibgeschützte Attribut __self__ auf das von *alist* bezeichnete Objekt gesetzt. (Das Attribut hat die gleiche Semantik wie bei anderen Instanzmethoden.)
3.2.8.8. Klassen¶
Klassen sind aufrufbar. Diese Objekte fungieren normalerweise als Fabriken für neue Instanzen von sich selbst, aber Variationen sind für Klassentypen möglich, die __new__() überschreiben. Die Argumente des Aufrufs werden an __new__() und im typischen Fall an __init__() übergeben, um die neue Instanz zu initialisieren.
3.2.8.9. Klasseninstanzen¶
Instanzen beliebiger Klassen können aufrufbar gemacht werden, indem eine Methode __call__() in ihrer Klasse definiert wird.
3.2.9. Module¶
Module sind eine grundlegende Organisationseinheit von Python-Code und werden vom Importsystem erstellt, entweder durch die Anweisung import oder durch Aufruf von Funktionen wie importlib.import_module() und die eingebaute Funktion __import__(). Ein Modulobjekt hat einen Namensraum, der durch ein Dictionary-Objekt implementiert ist (dies ist das Dictionary, auf das im Attribut __globals__ von Funktionen verwiesen wird, die im Modul definiert sind). Attributreferenzen werden in Lookups in diesem Dictionary übersetzt, z. B. ist m.x äquivalent zu m.__dict__["x"]. Ein Modulobjekt enthält nicht das Code-Objekt, das zur Initialisierung des Moduls verwendet wird (da es nach Abschluss der Initialisierung nicht mehr benötigt wird).
Attributzuweisungen aktualisieren das Namensraum-Dictionary des Moduls, z. B. ist m.x = 1 äquivalent zu m.__dict__["x"] = 1.
3.2.9.2. Andere beschreibbare Attribute von Module-Objekten¶
Neben den oben aufgeführten Import-bezogenen Attributen haben Modulobjekte auch die folgenden beschreibbaren Attribute:
- module.__doc__¶
Die Dokumentationszeichenkette des Moduls oder
None, wenn nicht verfügbar. Siehe auch:__doc__ Attribute.
- module.__annotations__¶
Ein Wörterbuch, das Variablenannotationen enthält, die während der Ausführung des Modulkörpers gesammelt wurden. Die besten Praktiken für die Arbeit mit
__annotations__finden Sie inannotationlib.Geändert in Version 3.14: Annotationen werden jetzt lazy ausgewertet. Siehe PEP 649.
- module.__annotate__¶
Die Annotate-Funktion für dieses Modul oder
None, wenn das Modul keine Annotationen hat. Siehe auch:__annotate__ Attribute.Hinzugefügt in Version 3.14.
3.2.9.3. Modul-Wörterbücher¶
Modulobjekte haben auch das folgende spezielle schreibgeschützte Attribut:
- module.__dict__¶
Der Namensraum des Moduls als Wörterbuchobjekt. Einzigartig unter den hier aufgeführten Attributen kann
__dict__nicht als globale Variable innerhalb eines Moduls zugegriffen werden; es kann nur als Attribut von Modulobjekten zugegriffen werden.CPython-Implementierungsdetail: Aufgrund der Art und Weise, wie CPython Modul-Wörterbücher löscht, wird das Modul-Wörterbuch gelöscht, wenn das Modul aus dem Geltungsbereich fällt, auch wenn das Wörterbuch noch Live-Referenzen hat. Um dies zu vermeiden, kopieren Sie das Wörterbuch oder behalten Sie das Modul bei, während Sie direkt auf sein Wörterbuch zugreifen.
3.2.10. Benutzerdefinierte Klassen¶
Benutzerdefinierte Klassentypen werden typischerweise durch Klassendefinitionen erstellt (siehe Abschnitt Klassendefinitionen). Eine Klasse hat einen Namensraum, der durch ein Wörterbuchobjekt implementiert wird. Klassenattributreferenzen werden in Lookups in diesem Wörterbuch übersetzt, z. B. wird C.x in C.__dict__["x"] übersetzt (obwohl es eine Reihe von Hooks gibt, die andere Mittel zur Lokalisierung von Attributen ermöglichen). Wenn der Attributname dort nicht gefunden wird, wird die Attributsuche in den Basisklassen fortgesetzt. Diese Suche in den Basisklassen verwendet die C3-Methodenauflösungsreihenfolge, die auch bei 'diamond'-Vererbungsszenarien korrekt funktioniert, bei denen mehrere Vererbungspfade zu einem gemeinsamen Vorfahren zurückführen. Zusätzliche Details zur von Python verwendeten C3 MRO finden Sie unter Die Python 2.3 Method Resolution Order.
Wenn eine Klassenattributreferenz (für die Klasse C, z. B.) ein Klassenmethodenobjekt ergibt, wird es in ein Instanzmethodenobjekt umgewandelt, dessen __self__-Attribut C ist. Wenn es ein staticmethod-Objekt ergibt, wird es in das vom statischen Methodenobjekt umschlossene Objekt umgewandelt. Siehe Abschnitt Implementierung von Deskriptoren für eine weitere Möglichkeit, wie Attribute, die von einer Klasse abgerufen werden, von denen abweichen können, die tatsächlich in ihrem __dict__ enthalten sind.
Klassenattributzuweisungen aktualisieren das Wörterbuch der Klasse, niemals das Wörterbuch einer Basisklasse.
Ein Klassenobjekt kann aufgerufen werden (siehe oben), um eine Klasseninstanz zu erzeugen (siehe unten).
3.2.10.1. Spezielle Attribute¶
Attribut |
Bedeutung |
|---|---|
|
Der Name der Klasse. Siehe auch: |
|
Der qualifizierte Name der Klasse. Siehe auch: |
|
Der Name des Moduls, in dem die Klasse definiert wurde. |
|
Ein |
|
Ein |
|
Die Dokumentationszeichenkette der Klasse oder |
|
Ein Wörterbuch, das Variablenannotationen enthält, die während der Ausführung des Klassenkörpers gesammelt wurden. Siehe auch: Die besten Praktiken für die Arbeit mit Warnung Der direkte Zugriff auf das Attribut Dieses Attribut existiert nicht auf bestimmten eingebauten Klassen. Auf benutzerdefinierten Klassen ohne Geändert in Version 3.14: Annotationen werden jetzt lazy ausgewertet. Siehe PEP 649. |
|
Die Annotate-Funktion für diese Klasse oder Hinzugefügt in Version 3.14. |
|
Ein Hinzugefügt in Version 3.12. |
|
Ein Hinzugefügt in Version 3.13. |
|
Die Zeilennummer der ersten Zeile der Klassendefinition, einschließlich Dekoratoren. Das Setzen des Attributs Hinzugefügt in Version 3.13. |
|
Das |
3.2.10.2. Spezielle Methoden¶
Zusätzlich zu den oben beschriebenen speziellen Attributen verfügen alle Python-Klassen auch über die folgenden beiden Methoden:
- type.mro()¶
Diese Methode kann von einer Metaklasse überschrieben werden, um die Methodenauflösungsreihenfolge für ihre Instanzen anzupassen. Sie wird bei der Klasseninstanziierung aufgerufen, und ihr Ergebnis wird in
__mro__gespeichert.
- type.__subclasses__()¶
Jede Klasse verwaltet eine Liste von schwachen Referenzen auf ihre unmittelbaren Unterklassen. Diese Methode gibt eine Liste aller noch lebenden Referenzen zurück. Die Liste ist in der Reihenfolge der Definition. Beispiel:
>>> class A: pass >>> class B(A): pass >>> A.__subclasses__() [<class 'B'>]
3.2.11. Klasseninstanzen¶
Eine Klasseninstanz wird durch Aufrufen eines Klassenobjekts (siehe oben) erstellt. Eine Klasseninstanz hat einen Namensraum, der als Wörterbuch implementiert ist und der erste Ort ist, an dem Attributreferenzen gesucht werden. Wenn ein Attribut dort nicht gefunden wird und die Klasse der Instanz ein Attribut mit diesem Namen hat, wird die Suche mit den Klassenattributen fortgesetzt. Wenn ein Klassenattribut gefunden wird, das ein benutzerdefiniertes Funktionsobjekt ist, wird es in ein Instanzmethodenobjekt umgewandelt, dessen __self__-Attribut die Instanz ist. Statische Methoden- und Klassenmethodenobjekte werden ebenfalls umgewandelt; siehe oben unter „Klassen“. Siehe Abschnitt Implementierung von Deskriptoren für eine weitere Möglichkeit, wie Attribute einer Klasse, die über ihre Instanzen abgerufen werden, von den Objekten abweichen können, die tatsächlich im __dict__ der Klasse gespeichert sind. Wenn kein Klassenattribut gefunden wird und die Klasse des Objekts eine __getattr__()-Methode hat, wird diese aufgerufen, um die Suche zu erfüllen.
Attributzuweisungen und -löschungen aktualisieren das Wörterbuch der Instanz, niemals das Wörterbuch einer Klasse. Wenn die Klasse eine __setattr__()- oder __delattr__()-Methode hat, wird diese anstelle der direkten Aktualisierung des Instanzwörterbuchs aufgerufen.
Klasseninstanzen können sich wie Zahlen, Sequenzen oder Wörterbücher verhalten, wenn sie Methoden mit bestimmten speziellen Namen haben. Siehe Abschnitt Spezielle Methodennamen.
3.2.11.1. Spezielle Attribute¶
- object.__class__¶
Die Klasse, zu der eine Klasseninstanz gehört.
3.2.12. E/A-Objekte (auch bekannt als Dateiobjekte)¶
Ein Dateiobjekt repräsentiert eine geöffnete Datei. Verschiedene Verknüpfungen sind verfügbar, um Dateiobjekte zu erstellen: die eingebaute Funktion open(), und auch os.popen(), os.fdopen() und die makefile()-Methode von Socket-Objekten (und vielleicht von anderen Funktionen oder Methoden, die von Erweiterungsmodulen bereitgestellt werden).
Die Objekte sys.stdin, sys.stdout und sys.stderr sind mit Dateiobjekten initialisiert, die den Standard-Ein-, Aus- und Fehlerströmen des Interpreters entsprechen; sie sind alle im Textmodus geöffnet und folgen daher der von der abstrakten Klasse io.TextIOBase definierten Schnittstelle.
3.2.13. Interne Typen¶
Einige vom Interpreter intern verwendete Typen werden dem Benutzer zugänglich gemacht. Ihre Definitionen können sich mit zukünftigen Versionen des Interpreters ändern, sie werden jedoch der Vollständigkeit halber hier erwähnt.
3.2.13.1. Code-Objekte¶
Code-Objekte repräsentieren *Byte-kompilierten* ausführbaren Python-Code oder Bytecode. Der Unterschied zwischen einem Code-Objekt und einem Funktions-Objekt besteht darin, dass das Funktions-Objekt eine explizite Referenz auf die Globale der Funktion (das Modul, in dem sie definiert wurde) enthält, während ein Code-Objekt keinen Kontext enthält; außerdem werden die Standardargumentwerte im Funktions-Objekt gespeichert, nicht im Code-Objekt (da sie Laufzeitwerte darstellen). Im Gegensatz zu Funktions-Objekten sind Code-Objekte unveränderlich und enthalten keine (direkten oder indirekten) Referenzen auf veränderliche Objekte.
3.2.13.1.1. Spezielle schreibgeschützte Attribute¶
|
Der Funktionsname. |
|
Der qualifizierte Funktionsname. Hinzugefügt in Version 3.11. |
|
Die Gesamtzahl der positionsbezogenen Parameter (einschließlich positionsbezogener Parameter und Parameter mit Standardwerten), die die Funktion hat. |
|
Die Anzahl der positionsbezogenen Parameter (einschließlich Argumente mit Standardwerten), die die Funktion hat. |
|
Die Anzahl der Schlüsselwort-only Parameter (einschließlich Argumente mit Standardwerten), die die Funktion hat. |
|
Die Anzahl der lokalen Variablen, die von der Funktion verwendet werden (einschließlich Parametern). |
|
Ein |
|
Ein |
|
Ein Hinweis: Verweise auf globale und eingebaute Namen sind nicht enthalten. |
|
Ein String, der die Sequenz von Bytecode-Instruktionen in der Funktion darstellt |
|
Ein |
|
Ein |
|
Der Name der Datei, aus der der Code kompiliert wurde |
|
Die Zeilennummer der ersten Zeile der Funktion |
|
Eine Zeichenkette, die die Zuordnung von Bytecode-Offsets zu Zeilennummern kodiert. Details finden Sie im Quellcode des Interpreters. Veraltet seit Version 3.12: Dieses Attribut von Code-Objekten ist veraltet und könnte in Python 3.15 entfernt werden. |
|
Die erforderliche Stack-Größe des Code-Objekts |
|
Ein |
Die folgenden Flag-Bits sind für co_flags definiert: Bit 0x04 ist gesetzt, wenn die Funktion die Syntax *arguments verwendet, um eine beliebige Anzahl von Positionsargumenten zu akzeptieren; Bit 0x08 ist gesetzt, wenn die Funktion die Syntax **keywords verwendet, um beliebige Schlüsselwortargumente zu akzeptieren; Bit 0x20 ist gesetzt, wenn die Funktion ein Generator ist. Details zur Semantik der einzelnen Flags finden Sie unter Code-Objekt-Bit-Flags.
Zukünftige Feature-Deklarationen (z.B. from __future__ import division) verwenden ebenfalls Bits in co_flags, um anzuzeigen, ob ein Code-Objekt mit einem bestimmten Feature kompiliert wurde. Siehe compiler_flag.
Andere Bits in co_flags sind für die interne Verwendung reserviert.
Wenn ein Code-Objekt eine Funktion darstellt und eine Docstring hat, ist das Bit CO_HAS_DOCSTRING in co_flags gesetzt und das erste Element in co_consts ist die Docstring der Funktion.
3.2.13.1.2. Methoden für Code-Objekte¶
- codeobject.co_positions()¶
Gibt ein iterierbares Objekt zurück, das die Quellcode-Positionen jeder Bytecode-Instruktion im Code-Objekt enthält.
Der Iterator gibt
Tupelzurück, die(start_line, end_line, start_column, end_column)enthalten. Das i-te Tupel entspricht der Position des Quellcodes, der zu der i-ten Code-Einheit kompiliert wurde. Spalteninformationen sind 0-indizierte UTF-8-Byte-Offsets in der angegebenen Quellzeile.Diese Positionsinformationen können fehlen. Eine nicht erschöpfende Liste von Fällen, in denen dies geschehen kann
Der Interpreter wird mit
-Xno_debug_rangesausgeführt.Laden einer pyc-Datei, die während der Verwendung von
-Xno_debug_rangeskompiliert wurde.Positions-Tupel, die künstlichen Instruktionen entsprechen.
Zeilen- und Spaltennummern, die aufgrund implementierungsspezifischer Einschränkungen nicht dargestellt werden können.
In diesem Fall können einige oder alle Tupel-Elemente
Nonesein.Hinzugefügt in Version 3.11.
Hinweis
Diese Funktion erfordert die Speicherung von Spaltenpositionen in Code-Objekten, was zu einer geringfügigen Erhöhung des Speicherbedarfs kompilierter Python-Dateien oder des Speicherbedarfs des Interpreters führen kann. Um die zusätzlichen Informationen nicht zu speichern und/oder die Ausgabe zusätzlicher Traceback-Informationen zu deaktivieren, können die Kommandozeilenoption
-Xno_debug_rangesoder die UmgebungsvariablePYTHONNODEBUGRANGESverwendet werden.
- codeobject.co_lines()¶
Gibt einen Iterator zurück, der Informationen über aufeinanderfolgende Bereiche von Bytecodes liefert. Jedes ausgegebene Element ist ein
(start, end, lineno)Tupelstart(einInteger) repräsentiert den Offset (inklusiv) des Beginns des Bytecode-Bereichsend(einInteger) repräsentiert den Offset (exklusiv) des Endes des Bytecode-Bereichslinenoist einInteger, der die Zeilennummer des Bytecode-Bereichs darstellt, oderNone, wenn die Bytecodes im gegebenen Bereich keine Zeilennummer haben
Die ausgegebenen Elemente haben folgende Eigenschaften
Der erste ausgegebene Bereich hat einen
startvon 0.Die
(start, end)-Bereiche sind nicht abnehmend und aufeinanderfolgend. Das heißt, für jedes Paar vonTupelnist derstartdes zweiten gleich demenddes ersten.Kein Bereich ist rückwärts:
end >= startfür alle Tripel.Das letzte ausgegebene
Tupelhatendgleich der Größe des Bytecodes.
Bereiche mit Null-Breite, bei denen
start == endist, sind zulässig. Bereiche mit Null-Breite werden für Zeilen verwendet, die im Quellcode vorhanden sind, aber vom Bytecode-Compiler eliminiert wurden.Hinzugefügt in Version 3.10.
Siehe auch
- PEP 626 - Genaue Zeilennummern für Debugging und andere Werkzeuge.
Die PEP, die die Methode
co_lines()eingeführt hat.
- codeobject.replace(**kwargs)¶
Gibt eine Kopie des Code-Objekts mit neuen Werten für die angegebenen Felder zurück.
Code-Objekte werden auch von der generischen Funktion
copy.replace()unterstützt.Hinzugefügt in Version 3.8.
3.2.13.2. Frame-Objekte¶
Frame-Objekte repräsentieren Ausführungs-Frames. Sie können in Traceback-Objekten auftreten und werden auch an registrierte Trace-Funktionen übergeben.
3.2.13.2.1. Spezielle schreibgeschützte Attribute¶
|
Verweist auf den vorherigen Stack-Frame (in Richtung Aufrufer) oder |
|
Das Code-Objekt, das in diesem Frame ausgeführt wird. Der Zugriff auf dieses Attribut löst ein Audit-Ereignis |
|
Die Zuordnung, die vom Frame verwendet wird, um lokale Variablen nachzuschlagen. Wenn der Frame auf einen optimierten Geltungsbereich verweist, kann dies ein Write-Through-Proxy-Objekt zurückgeben. Geändert in Version 3.13: Gibt einen Proxy für optimierte Geltungsbereiche zurück. |
|
Das Dictionary, das vom Frame zum Nachschlagen von globalen Variablen verwendet wird |
|
Das Dictionary, das vom Frame zum Nachschlagen von eingebauten (intrinsischen) Namen verwendet wird |
|
Die „präzise Instruktion“ des Frame-Objekts (dies ist ein Index in die Bytecode-Zeichenkette des Code-Objekts) |
|
Das Generator- oder Coroutine-Objekt, dem dieser Frame gehört, oder Hinzugefügt in Version 3.14. |
3.2.13.2.2. Spezielle beschreibbare Attribute¶
|
Wenn nicht |
|
Setzen Sie dieses Attribut auf |
|
Setzen Sie dieses Attribut auf |
|
Die aktuelle Zeilennummer des Frames – Schreiben in dieses Attribut von innerhalb einer Trace-Funktion springt zur angegebenen Zeile (nur für den untersten Frame). Ein Debugger kann einen Sprungbefehl (auch bekannt als „Nächste Anweisung festlegen“) implementieren, indem er in dieses Attribut schreibt. |
3.2.13.2.3. Frame-Objekt-Methoden¶
Frame-Objekte unterstützen eine Methode
- frame.clear()¶
Diese Methode löscht alle Referenzen auf lokale Variablen, die vom Frame gehalten werden. Wenn der Frame zu einem Generator gehörte, wird der Generator auch finalisiert. Dies hilft, Referenzzyklen zu brechen, die Frame-Objekte betreffen (z.B. beim Abfangen einer Ausnahme und Speichern ihres Tracebacks für spätere Verwendung).
RuntimeErrorwird ausgelöst, wenn der Frame gerade ausgeführt wird oder suspendiert ist.Hinzugefügt in Version 3.4.
Geändert in Version 3.13: Der Versuch, einen suspendierten Frame zu löschen, löst
RuntimeErroraus (wie es für ausgeführte Frames immer der Fall war).
3.2.13.3. Traceback-Objekte¶
Traceback-Objekte repräsentieren den Stack-Trace einer Ausnahme. Ein Traceback-Objekt wird implizit erstellt, wenn eine Ausnahme auftritt, und kann auch explizit durch Aufrufen von types.TracebackType erstellt werden.
Geändert in Version 3.7: Traceback-Objekte können jetzt explizit aus Python-Code instanziiert werden.
Für implizit erstellte Tracebacks wird bei der Suche nach einem Ausnahmebehandler, der den Ausführungs-Stack entwirrt, auf jeder entwirrten Ebene ein Traceback-Objekt vor dem aktuellen Traceback eingefügt. Wenn ein Ausnahmebehandler betreten wird, wird der Stack-Trace dem Programm zur Verfügung gestellt. (Siehe Abschnitt Die try-Anweisung.) Er ist als drittes Element des von sys.exc_info() zurückgegebenen Tupels und als Attribut __traceback__ der abgefangenen Ausnahme zugänglich.
Wenn das Programm keinen geeigneten Behandler enthält, wird der Stack-Trace (schön formatiert) auf den Standardfehlerstrom geschrieben; wenn der Interpreter interaktiv ist, wird er dem Benutzer auch als sys.last_traceback zur Verfügung gestellt.
Für explizit erstellte Tracebacks obliegt es dem Ersteller des Tracebacks, zu bestimmen, wie die Attribute tb_next verknüpft werden sollen, um einen vollständigen Stack-Trace zu bilden.
Spezielle schreibgeschützte Attribute
|
Verweist auf den Ausführungs-Frame der aktuellen Ebene. Der Zugriff auf dieses Attribut löst ein Audit-Ereignis |
|
Gibt die Zeilennummer an, an der die Ausnahme aufgetreten ist |
|
Gibt die „präzise Instruktion“ an. |
Die Zeilennummer und die letzte Instruktion im Traceback können von der Zeilennummer ihres Frame-Objekts abweichen, wenn die Ausnahme in einer try-Anweisung ohne passende except-Klausel oder mit einer finally-Klausel aufgetreten ist.
- traceback.tb_next¶
Das spezielle beschreibbare Attribut
tb_nextist die nächste Ebene im Stack-Trace (in Richtung des Frames, in dem die Ausnahme aufgetreten ist), oderNone, wenn keine nächste Ebene vorhanden ist.Geändert in Version 3.7: Dieses Attribut ist jetzt beschreibbar
3.2.13.4. Slice-Objekte¶
Slice-Objekte werden verwendet, um Slices für __getitem__()-Methoden darzustellen. Sie werden auch von der eingebauten Funktion slice() erstellt.
Spezielle schreibgeschützte Attribute: start ist die untere Grenze; stop ist die obere Grenze; step ist der Schrittwert; jeder ist None, wenn er weggelassen wird. Diese Attribute können jeden Typ haben.
Slice-Objekte unterstützen eine Methode
- slice.indices(self, length)¶
Diese Methode nimmt ein einzelnes ganzzahliges Argument length und berechnet Informationen über den Slice, den das Slice-Objekt beschreiben würde, wenn es auf eine Sequenz von length Elementen angewendet wird. Sie gibt ein Tupel von drei ganzen Zahlen zurück; dies sind jeweils der Start- und Stop-Index sowie die Schrittweite oder Schrittlänge des Slices. Fehlende oder außerhalb des Bereichs liegende Indizes werden konsistent mit regulären Slices behandelt.
3.2.13.5. Static-Methoden-Objekte¶
Static-Methoden-Objekte bieten eine Möglichkeit, die Transformation von Funktions-Objekten in Methoden-Objekte zu verhindern, wie oben beschrieben. Ein Static-Methoden-Objekt ist ein Wrapper um ein beliebiges anderes Objekt, normalerweise ein benutzerdefiniertes Methoden-Objekt. Wenn ein Static-Methoden-Objekt von einer Klasse oder einer Klasseninstanz abgerufen wird, ist das tatsächlich zurückgegebene Objekt das verpackte Objekt, das keiner weiteren Transformation unterliegt. Static-Methoden-Objekte sind ebenfalls aufrufbar. Static-Methoden-Objekte werden vom eingebauten Konstruktor staticmethod() erstellt.
3.2.13.6. Klassenmethoden-Objekte¶
Ein Klassenmethoden-Objekt ist, ähnlich einem Static-Methoden-Objekt, ein Wrapper um ein anderes Objekt, das die Art und Weise verändert, wie dieses Objekt von Klassen und Klasseninstanzen abgerufen wird. Das Verhalten von Klassenmethoden-Objekten bei einem solchen Abruf wird oben unter „Instanzmethoden“ beschrieben. Klassenmethoden-Objekte werden vom eingebauten Konstruktor classmethod() erstellt.
3.3. Spezielle Methodennamen¶
Eine Klasse kann bestimmte Operationen implementieren, die durch spezielle Syntax aufgerufen werden (wie arithmetische Operationen oder Indizierung und Slicing), indem sie Methoden mit speziellen Namen definiert. Dies ist Pythons Ansatz für Operatorüberladung, der es Klassen ermöglicht, ihr eigenes Verhalten in Bezug auf Sprachoperatoren zu definieren. Wenn eine Klasse beispielsweise eine Methode namens __getitem__() definiert und x eine Instanz dieser Klasse ist, dann ist x[i] ungefähr äquivalent zu type(x).__getitem__(x, i). Sofern nicht anders angegeben, wird beim Versuch, eine Operation auszuführen, eine Ausnahme ausgelöst, wenn keine geeignete Methode definiert ist (typischerweise AttributeError oder TypeError).
Das Setzen einer speziellen Methode auf None zeigt an, dass die entsprechende Operation nicht verfügbar ist. Wenn eine Klasse beispielsweise __iter__() auf None setzt, ist die Klasse nicht iterierbar, sodass das Aufrufen von iter() für ihre Instanzen eine TypeError auslöst (ohne auf __getitem__() zurückzufallen). [2]
Beim Implementieren einer Klasse, die einen eingebauten Typ emuliert, ist es wichtig, dass die Emulation nur in dem Maße implementiert wird, wie es für das modellierte Objekt sinnvoll ist. Beispielsweise können einige Sequenzen gut mit dem Abrufen einzelner Elemente funktionieren, aber das Extrahieren eines Slices ist möglicherweise nicht sinnvoll. (Ein Beispiel hierfür ist die NodeList-Schnittstelle im Document Object Model des W3C.)
3.3.1. Grundlegende Anpassung¶
- object.__new__(cls[, ...])¶
Wird aufgerufen, um eine neue Instanz der Klasse cls zu erstellen.
__new__()ist eine statische Methode (speziell behandelt, sodass Sie sie nicht als solche deklarieren müssen), die die Klasse, für die eine Instanz angefordert wurde, als erstes Argument nimmt. Die restlichen Argumente sind diejenigen, die dem Ausdruck zur Objekterstellung übergeben werden (dem Aufruf der Klasse). Der Rückgabewert von__new__()sollte die neue Instanz des Objekts sein (normalerweise eine Instanz von cls).Typische Implementierungen erstellen eine neue Instanz der Klasse, indem sie die
__new__()-Methode der Oberklasse mitsuper().__new__(cls[, ...])mit geeigneten Argumenten aufrufen und dann die neu erstellte Instanz nach Bedarf ändern, bevor sie zurückgegeben wird.Wenn
__new__()während der Objekterstellung aufgerufen wird und eine Instanz von cls zurückgibt, dann wird die__init__()-Methode der neuen Instanz wie folgt aufgerufen:__init__(self[, ...]), wobei self die neue Instanz ist und die verbleibenden Argumente dieselben sind, die an den Objektkonstruktor übergeben wurden.Wenn
__new__()keine Instanz von cls zurückgibt, dann wird die__init__()-Methode der neuen Instanz nicht aufgerufen.__new__()ist hauptsächlich dazu gedacht, Unterklassen unveränderlicher Typen (wie int, str oder tuple) die Anpassung der Instanzerstellung zu ermöglichen. Es wird auch häufig in benutzerdefinierten Metaklassen überschrieben, um die Klassenerstellung anzupassen.
- object.__init__(self[, ...])¶
Wird aufgerufen, nachdem die Instanz erstellt wurde (durch
__new__()), aber bevor sie an den Aufrufer zurückgegeben wird. Die Argumente sind diejenigen, die dem Konstruktorausdruck der Klasse übergeben wurden. Wenn eine Basisklasse eine__init__()-Methode hat, muss die__init__()-Methode der abgeleiteten Klasse, falls vorhanden, diese explizit aufrufen, um die ordnungsgemäße Initialisierung des Basisklassen-Teils der Instanz sicherzustellen; zum Beispiel:super().__init__([args...]).Da
__new__()und__init__()bei der Konstruktion von Objekten zusammenarbeiten (__new__()zum Erstellen, und__init__()zum Anpassen), darf von__init__()kein anderer Wert alsNonezurückgegeben werden; andernfalls wird zur Laufzeit einTypeErrorausgelöst.
- object.__del__(self)¶
Wird aufgerufen, wenn die Instanz zerstört werden soll. Dies wird auch als Finalizer oder (fälschlicherweise) als Destruktor bezeichnet. Wenn eine Basisklasse eine
__del__()-Methode hat, muss die__del__()-Methode der abgeleiteten Klasse, falls vorhanden, diese explizit aufrufen, um die ordnungsgemäße Zerstörung des Basisklassen-Teils der Instanz sicherzustellen.Es ist möglich (wenn auch nicht empfohlen!), dass die
__del__()-Methode die Zerstörung der Instanz hinauszögert, indem sie eine neue Referenz darauf erstellt. Dies wird als Auferstehung des Objekts bezeichnet. Es ist implementierungsabhängig, ob__del__()bei der Zerstörung eines auferstandenen Objekts ein zweites Mal aufgerufen wird; die aktuelle CPython-Implementierung ruft sie nur einmal auf.Es ist nicht garantiert, dass
__del__()-Methoden für Objekte aufgerufen werden, die noch existieren, wenn der Interpreter beendet wird.weakref.finalizebietet eine einfache Möglichkeit, eine Bereinigungsfunktion zu registrieren, die aufgerufen wird, wenn ein Objekt vom Garbage Collector eingesammelt wird.Hinweis
del xruftx.__del__()nicht direkt auf – ersteres dekrementiert den Referenzzähler fürxum eins, und letzteres wird nur aufgerufen, wenn der Referenzzähler vonxnull erreicht.CPython-Implementierungsdetail: Es ist möglich, dass ein Referenzzyklus verhindert, dass der Referenzzähler eines Objekts auf null fällt. In diesem Fall wird der Zyklus später vom zyklischen Garbage Collector erkannt und gelöscht. Eine häufige Ursache für Referenzzyklen ist, wenn eine Ausnahme in einer lokalen Variable abgefangen wurde. Die Locals des Frames referenzieren dann die Ausnahme, die ihre eigene Traceback referenziert, die die Locals aller im Traceback abgefangenen Frames referenziert.
Siehe auch
Dokumentation für das Modul
gc.Warnung
Aufgrund der prekären Umstände, unter denen
__del__()-Methoden aufgerufen werden, werden Ausnahmen, die während ihrer Ausführung auftreten, ignoriert und stattdessen eine Warnung aufsys.stderrausgegeben. Insbesondere__del__()kann aufgerufen werden, wenn beliebiger Code ausgeführt wird, einschließlich Code von einem beliebigen Thread. Wenn__del__()eine Sperre ergreifen oder eine andere blockierende Ressource aufrufen muss, kann es zu einer Deadlock-Situation kommen, da die Ressource möglicherweise bereits vom Code belegt ist, der unterbrochen wird, um__del__()auszuführen.__del__()kann während der Beendigung des Interpreters ausgeführt werden. Infolgedessen können globale Variablen, auf die es zugreifen muss (einschließlich anderer Module), bereits gelöscht oder aufNonegesetzt worden sein. Python garantiert, dass globale Variablen, deren Name mit einem einzelnen Unterstrich beginnt, vor anderen globalen Variablen aus ihrem Modul gelöscht werden; wenn keine anderen Referenzen auf solche globalen Variablen existieren, kann dies dazu beitragen, dass importierte Module zum Zeitpunkt des Aufrufs der__del__()-Methode noch verfügbar sind.
- object.__repr__(self)¶
Wird von der eingebauten Funktion
repr()aufgerufen, um die „offizielle“ Zeichenkettenrepräsentation eines Objekts zu berechnen. Wenn möglich, sollte dies wie ein gültiger Python-Ausdruck aussehen, der verwendet werden könnte, um ein Objekt mit demselben Wert (in einer geeigneten Umgebung) neu zu erstellen. Wenn dies nicht möglich ist, sollte ein String der Form<...irgendeine nützliche Beschreibung...>zurückgegeben werden. Der Rückgabewert muss ein Zeichenkettenobjekt sein. Wenn eine Klasse__repr__(), aber nicht__str__()definiert, dann wird__repr__()auch verwendet, wenn eine „informelle“ Zeichenkettenrepräsentation von Instanzen dieser Klasse erforderlich ist.Dies wird typischerweise für Debuggingzwecke verwendet, daher ist es wichtig, dass die Darstellung informativ und eindeutig ist. Eine Standardimplementierung wird von der Klasse
objectselbst bereitgestellt.
- object.__str__(self)¶
Wird von
str(object), der Standardimplementierung von__format__()und der eingebauten Funktionprint()aufgerufen, um die „informelle“ oder gut lesbare Zeichenkettenrepräsentation eines Objekts zu berechnen. Der Rückgabewert muss ein str-Objekt sein.Diese Methode unterscheidet sich von
object.__repr__()dadurch, dass von__str__()kein gültiger Python-Ausdruck erwartet wird: Eine praktischere oder prägnantere Darstellung kann verwendet werden.Die Standardimplementierung des eingebauten Typs
objectruftobject.__repr__()auf.
- object.__bytes__(self)¶
Wird von bytes aufgerufen, um eine Byte-String-Repräsentation eines Objekts zu berechnen. Dies sollte ein
bytes-Objekt zurückgeben. Die Klasseobjectselbst stellt diese Methode nicht bereit.
- object.__format__(self, format_spec)¶
Wird von der eingebauten Funktion
format()und damit von der Auswertung von formatierten Zeichenkettenliteralen und der Methodestr.format()aufgerufen, um eine „formatierte“ Zeichenkettenrepräsentation eines Objekts zu erzeugen. Das Argument format_spec ist eine Zeichenkette, die eine Beschreibung der gewünschten Formatierungsoptionen enthält. Die Interpretation des Arguments format_spec obliegt dem Typ, der__format__()implementiert. Die meisten Klassen werden jedoch entweder die Formatierung an einen der eingebauten Typen delegieren oder eine ähnliche Formatierungsoptionssyntax verwenden.Siehe Format Specification Mini-Language für eine Beschreibung der Standardformatierungssyntax.
Der Rückgabewert muss ein Zeichenkettenobjekt sein.
Die Standardimplementierung der Klasse
objectsollte eine leere format_spec Zeichenkette erhalten. Sie delegiert an__str__().Geändert in Version 3.4: Die __format__-Methode von
objectselbst löst einenTypeErroraus, wenn eine nicht leere Zeichenkette übergeben wird.Geändert in Version 3.7:
object.__format__(x, '')ist nun äquivalent zustr(x)statt zuformat(str(x), '').
- object.__lt__(self, other)¶
- object.__le__(self, other)¶
- object.__eq__(self, other)¶
- object.__ne__(self, other)¶
- object.__gt__(self, other)¶
- object.__ge__(self, other)¶
Dies sind die sogenannten „Rich Comparison“-Methoden. Die Entsprechung zwischen Operatorsymbolen und Methodennamen ist wie folgt:
x<yruftx.__lt__(y)auf,x<=yruftx.__le__(y)auf,x==yruftx.__eq__(y)auf,x!=yruftx.__ne__(y)auf,x>yruftx.__gt__(y)auf undx>=yruftx.__ge__(y)auf.Eine Rich Comparison-Methode kann das Singleton
NotImplementedzurückgeben, wenn sie die Operation für ein gegebenes Paar von Argumenten nicht implementiert. Konventionsgemäß werdenFalseundTruefür einen erfolgreichen Vergleich zurückgegeben. Diese Methoden können jedoch jeden Wert zurückgeben, sodass, wenn der Vergleichsoperator in einem booleschen Kontext verwendet wird (z. B. in der Bedingung einerif-Anweisung), Pythonbool()auf den Wert anwendet, um zu bestimmen, ob das Ergebnis wahr oder falsch ist.Standardmäßig implementiert
object__eq__()durch die Verwendung vonisund gibtNotImplementedim Falle eines falschen Vergleichs zurück:True if x is y else NotImplemented. Für__ne__()delegiert es standardmäßig an__eq__()und invertiert das Ergebnis, es sei denn, es istNotImplemented. Es gibt keine anderen impliziten Beziehungen zwischen den Vergleichsoperatoren oder Standardimplementierungen; die Wahrheit von(x<y or x==y)impliziert beispielsweise nichtx<=y. Um Ordering-Operationen automatisch aus einer einzelnen Wurzeloperation zu generieren, siehefunctools.total_ordering().Standardmäßig stellt die Klasse
objectImplementierungen bereit, die mit Wertvergleichen konsistent sind: Gleichheit vergleicht nach Objektidentität und Ordnungsvergleiche lösen einenTypeErroraus. Jede Standardmethode kann diese Ergebnisse direkt generieren, kann aber auchNotImplementedzurückgeben.Siehe den Abschnitt über
__hash__()für einige wichtige Hinweise zur Erstellung von hashbaren Objekten, die benutzerdefinierte Vergleichsoperationen unterstützen und als Dictionary-Schlüssel verwendet werden können.Es gibt keine vertauschten Argumentversionen dieser Methoden (die verwendet werden sollen, wenn das linke Argument die Operation nicht unterstützt, das rechte Argument jedoch schon); stattdessen sind
__lt__()und__gt__()gegenseitige Spiegelbilder,__le__()und__ge__()sind gegenseitige Spiegelbilder, und__eq__()und__ne__()sind ihre eigenen Spiegelbilder. Wenn die Operanden unterschiedliche Typen haben und der Typ des rechten Operanden ein direkter oder indirekter Untertyp des Typs des linken Operanden ist, hat die gespiegelte Methode des rechten Operanden Priorität, andernfalls hat die Methode des linken Operanden Priorität. Virtuelles Vererbung wird nicht berücksichtigt.Wenn keine geeignete Methode einen anderen Wert als
NotImplementedzurückgibt, fallen die Operatoren==und!=aufisundis notzurück.
- object.__hash__(self)¶
Wird von der eingebauten Funktion
hash()und für Operationen auf Mitgliedern von gehashten Sammlungen, einschließlichset,frozensetunddict, aufgerufen. Die Methode__hash__()sollte eine Ganzzahl zurückgeben. Die einzige erforderliche Eigenschaft ist, dass Objekte, die gleich verglichen werden, denselben Hash-Wert haben. Es wird empfohlen, die Hash-Werte der Komponenten des Objekts, die auch beim Vergleich von Objekten eine Rolle spielen, zu mischen, indem sie in ein Tupel gepackt und das Tupel gehasht werden. Beispieldef __hash__(self): return hash((self.name, self.nick, self.color))
Hinweis
hash()kürzt den von der benutzerdefinierten__hash__()-Methode eines Objekts zurückgegebenen Wert auf die Größe einesPy_ssize_t. Dies sind typischerweise 8 Bytes bei 64-Bit-Builds und 4 Bytes bei 32-Bit-Builds. Wenn die__hash__()-Methode eines Objekts auf Builds mit unterschiedlicher Bitgröße interoperabel sein muss, stellen Sie sicher, dass Sie die Breite auf allen unterstützten Builds überprüfen. Eine einfache Möglichkeit, dies zu tun, ist mitpython -c "import sys; print(sys.hash_info.width)".Wenn eine Klasse keine
__eq__()-Methode definiert, sollte sie auch keine__hash__()-Operation definieren; wenn sie__eq__(), aber nicht__hash__()definiert, sind ihre Instanzen nicht als Elemente in hashbaren Sammlungen verwendbar. Wenn eine Klasse veränderliche Objekte definiert und eine__eq__()-Methode implementiert, sollte sie keine__hash__()implementieren, da die Implementierung von hashbaren Sammlungen erfordert, dass der Hash-Wert eines Schlüssels unveränderlich ist (wenn sich der Hash-Wert des Objekts ändert, befindet es sich im falschen Hash-Bucket).Benutzerdefinierte Klassen haben standardmäßig
__eq__()- und__hash__()-Methoden (geerbt von der Klasseobject); mit ihnen sind alle Objekte ungleich (außer mit sich selbst) undx.__hash__()gibt einen geeigneten Wert zurück, sodassx == ysowohl impliziert, dassx is y, als auch dasshash(x) == hash(y).Eine Klasse, die
__eq__()überschreibt und keine__hash__()definiert, wird ihre__hash__()implizit aufNonesetzen. Wenn die__hash__()-Methode einer KlasseNoneist, lösen Instanzen der Klasse einen entsprechendenTypeErroraus, wenn ein Programm versucht, ihren Hash-Wert abzurufen, und werden auch korrekt als unhashbar identifiziert, wennisinstance(obj, collections.abc.Hashable)überprüft wird.Wenn eine Klasse, die
__eq__()überschreibt, die Implementierung von__hash__()einer übergeordneten Klasse beibehalten muss, muss dem Interpreter dies explizit mitgeteilt werden, indem__hash__ = <ParentClass>.__hash__gesetzt wird.Wenn eine Klasse, die
__eq__()nicht überschreibt, die Hash-Unterstützung unterdrücken möchte, sollte sie__hash__ = Nonein die Klassendefinition aufnehmen. Eine Klasse, die ihre eigene__hash__()definiert, die explizit einenTypeErrorauslöst, würde bei einem Aufruf vonisinstance(obj, collections.abc.Hashable)fälschlicherweise als hashbar identifiziert werden.Hinweis
Standardmäßig werden die
__hash__()-Werte von str- und bytes-Objekten mit einem unvorhersehbaren Zufallswert „gesalzen“. Obwohl sie innerhalb eines einzelnen Python-Prozesses konstant bleiben, sind sie zwischen wiederholten Aufrufen von Python nicht vorhersagbar.Dies dient dem Schutz vor Denial-of-Service-Angriffen, die durch sorgfältig ausgewählte Eingaben verursacht werden und die Worst-Case-Performance einer Dictionary-Einfügung, O(n2) Komplexität, ausnutzen. Siehe http://ocert.org/advisories/ocert-2011-003.html für Details.
Das Ändern von Hash-Werten beeinflusst die Iterationsreihenfolge von Sets. Python hat nie Garantien für diese Reihenfolge gemacht (und sie variiert typischerweise zwischen 32-Bit- und 64-Bit-Builds).
Siehe auch
PYTHONHASHSEED.Geändert in Version 3.3: Hash-Randomisierung ist standardmäßig aktiviert.
- object.__bool__(self)¶
Wird aufgerufen, um die Wahrheitswertprüfung und die eingebaute Operation
bool()zu implementieren; sollteFalseoderTruezurückgeben. Wenn diese Methode nicht definiert ist, wird__len__()aufgerufen, wenn sie definiert ist, und das Objekt wird als wahr betrachtet, wenn sein Ergebnis ungleich Null ist. Wenn eine Klasse weder__len__()noch__bool__()definiert (was für die Klasseobjectselbst gilt), gelten alle ihre Instanzen als wahr.
3.3.2. Anpassen des Attributzugriffs¶
Die folgenden Methoden können definiert werden, um die Bedeutung des Attributzugriffs (Verwendung von, Zuweisung zu oder Löschen von x.name) für Klasseninstanzen anzupassen.
- object.__getattr__(self, name)¶
Wird aufgerufen, wenn der Standard-Attributzugriff mit einem
AttributeErrorfehlschlägt (entweder löst__getattribute__()einenAttributeErroraus, weil name kein Instanzattribut oder kein Attribut im Klassbaum fürselfist; oder__get__()einer name-Eigenschaft löst einenAttributeErroraus). Diese Methode sollte entweder den (berechneten) Attributwert zurückgeben oder eineAttributeError-Ausnahme auslösen. Die Klasseobjectselbst stellt diese Methode nicht bereit.Beachten Sie, dass, wenn das Attribut über den normalen Mechanismus gefunden wird,
__getattr__()nicht aufgerufen wird. (Dies ist eine beabsichtigte Asymmetrie zwischen__getattr__()und__setattr__().) Dies geschieht sowohl aus Effizienzgründen als auch, weil ansonsten__getattr__()keinen Zugriff auf andere Attribute der Instanz hätte. Beachten Sie, dass Sie zumindest für Instanzvariablen die volle Kontrolle übernehmen können, indem Sie keine Werte im Attributwörterbuch der Instanz einfügen (sondern sie stattdessen in einem anderen Objekt einfügen). Siehe die Methode__getattribute__()unten für eine Möglichkeit, tatsächlich die volle Kontrolle über den Attributzugriff zu erhalten.
- object.__getattribute__(self, name)¶
Wird bedingungslos aufgerufen, um Attributzugriffe für Instanzen der Klasse zu implementieren. Wenn die Klasse auch
__getattr__()definiert, wird letzteres nicht aufgerufen, es sei denn,__getattribute__()ruft es explizit auf oder löst eineAttributeErroraus. Diese Methode sollte den (berechneten) Attributwert zurückgeben oder eineAttributeErrorAusnahme auslösen. Um eine unendliche Rekursion in dieser Methode zu vermeiden, sollte ihre Implementierung immer die Basisklassenmethode mit demselben Namen aufrufen, um auf benötigte Attribute zuzugreifen, z.B.object.__getattribute__(self, name).Hinweis
Diese Methode kann bei der Suche nach speziellen Methoden, die sich aus der impliziten Invokation über die Sprachsyntax oder eingebaute Funktionen ergeben, immer noch umgangen werden. Siehe Sonderfall-Suche.
Bei bestimmten sensiblen Attributzugriffen wird ein Audit-Ereignis
object.__getattr__mit den Argumentenobjundnameausgelöst.
- object.__setattr__(self, name, value)¶
Wird aufgerufen, wenn eine Attributzuweisung versucht wird. Dies geschieht anstelle des normalen Mechanismus (d.h. Speichern des Werts im Instanzwörterbuch). name ist der Attributname, value ist der zuzuweisende Wert.
Wenn
__setattr__()einem Instanzattribut eine Zuweisung vornehmen möchte, sollte es die Basisklassenmethode mit demselben Namen aufrufen, z.B.object.__setattr__(self, name, value).Bei bestimmten sensiblen Attributzuweisungen wird ein Audit-Ereignis
object.__setattr__mit den Argumentenobj,name,valueausgelöst.
- object.__delattr__(self, name)¶
Ähnlich wie
__setattr__(), aber für das Löschen von Attributen anstelle von Zuweisungen. Dies sollte nur implementiert werden, wenndel obj.namefür das Objekt sinnvoll ist.Bei bestimmten sensiblen Attributlöschungen wird ein Audit-Ereignis
object.__delattr__mit den Argumentenobjundnameausgelöst.
- object.__dir__(self)¶
Wird aufgerufen, wenn
dir()auf das Objekt angewendet wird. Ein iterierbares Objekt muss zurückgegeben werden.dir()wandelt das zurückgegebene iterierbare Objekt in eine Liste um und sortiert diese.
3.3.2.1. Anpassen des Zugriffs auf Modulattribute¶
Spezielle Namen wie __getattr__ und __dir__ können ebenfalls verwendet werden, um den Zugriff auf Modulattribute anzupassen. Die __getattr__-Funktion auf Modulebene sollte ein Argument akzeptieren, das den Namen eines Attributs ist, und den berechneten Wert zurückgeben oder eine AttributeError auslösen. Wenn ein Attribut auf einem Modulobjekt über die normale Suche, d.h. object.__getattribute__(), nicht gefunden wird, dann wird __getattr__ im __dict__ des Moduls gesucht, bevor eine AttributeError ausgelöst wird. Wenn gefunden, wird sie mit dem Attributnamen aufgerufen und das Ergebnis zurückgegeben.
Die Funktion __dir__ sollte keine Argumente akzeptieren und ein iterierbares Objekt von Zeichenketten zurückgeben, das die auf dem Modul zugänglichen Namen darstellt. Wenn vorhanden, überschreibt diese Funktion die Standard-dir()-Suche auf einem Modul.
- module.__class__¶
Für eine feinere Anpassung des Modulverhaltens (Setzen von Attributen, Eigenschaften usw.) kann das Attribut __class__ eines Modulobjekts auf eine Unterklasse von types.ModuleType gesetzt werden. Zum Beispiel
import sys
from types import ModuleType
class VerboseModule(ModuleType):
def __repr__(self):
return f'Verbose {self.__name__}'
def __setattr__(self, attr, value):
print(f'Setting {attr}...')
super().__setattr__(attr, value)
sys.modules[__name__].__class__ = VerboseModule
Hinweis
Das Definieren von Modul __getattr__ und das Setzen von Modul __class__ wirkt sich nur auf Lookups aus, die über die Attributzugriffssyntax erfolgen – direkter Zugriff auf die globalen Variablen des Moduls (sei es durch Code innerhalb des Moduls oder über eine Referenz auf das globale Wörterbuch des Moduls) ist davon unberührt.
Geändert in Version 3.5: Das Modulattribut __class__ ist jetzt beschreibbar.
Hinzugefügt in Version 3.7: Modulattribute __getattr__ und __dir__.
Siehe auch
- PEP 562 – Module __getattr__ und __dir__
Beschreibt die Funktionen
__getattr__und__dir__in Modulen.
3.3.2.2. Implementieren von Deskriptoren¶
Die folgenden Methoden gelten nur, wenn eine Instanz der Klasse, die die Methode enthält (eine sogenannte *Deskriptorklasse*), in einer *Besitzerklasse* (die Deskriptorklasse muss sich entweder im Klassenwörterbuch des Besitzers oder im Klassenwörterbuch eines seiner Elternteile befinden) erscheint. In den folgenden Beispielen bezieht sich "das Attribut" auf das Attribut, dessen Name der Schlüssel der Eigenschaft im __dict__ der Besitzerklasse ist. Die Klasse object selbst implementiert kein dieser Protokolle.
- object.__get__(self, instance, owner=None)¶
Wird aufgerufen, um das Attribut der Besitzerklasse (Klassenattributzugriff) oder einer Instanz dieser Klasse (Instanzattributzugriff) zu erhalten. Das optionale Argument owner ist die Besitzerklasse, während instance die Instanz ist, über die auf das Attribut zugegriffen wurde, oder
None, wenn auf das Attribut über den owner zugegriffen wurde.Diese Methode sollte den berechneten Attributwert zurückgeben oder eine
AttributeErrorAusnahme auslösen.PEP 252 gibt vor, dass
__get__()mit einem oder zwei Argumenten aufrufbar ist. Pythons eigene eingebaute Deskriptoren unterstützen diese Spezifikation; es ist jedoch wahrscheinlich, dass einige Tools von Drittanbietern Deskriptoren haben, die beide Argumente benötigen. Pythons eigene Implementierung von__getattribute__()übergibt immer beide Argumente, ob sie benötigt werden oder nicht.
- object.__set__(self, instance, value)¶
Wird aufgerufen, um das Attribut einer Instanz instance der Besitzerklasse auf einen neuen Wert value zu setzen.
Beachten Sie, dass das Hinzufügen von
__set__()oder__delete__()die Art des Deskriptors in einen "Daten-Deskriptor" ändert. Weitere Details finden Sie unter Aufrufen von Deskriptoren.
- object.__delete__(self, instance)¶
Wird aufgerufen, um das Attribut einer Instanz instance der Besitzerklasse zu löschen.
Instanzen von Deskriptoren können auch das Attribut __objclass__ haben
- object.__objclass__¶
Das Attribut
__objclass__wird vominspect-Modul interpretiert als Angabe der Klasse, in der dieses Objekt definiert wurde (eine entsprechende Einstellung kann die Laufzeit-Introspektion von dynamischen Klassenattributen unterstützen). Für aufrufbare Objekte kann es darauf hinweisen, dass eine Instanz des gegebenen Typs (oder eine Unterklasse) als erstes Positionsargument erwartet oder erforderlich ist (z.B. setzt CPython dieses Attribut für ungebundene Methoden, die in C implementiert sind).
3.3.2.3. Aufrufen von Deskriptoren¶
Im Allgemeinen ist ein Deskriptor ein Objektattribut mit "Bindungsverhalten", dessen Attributzugriff durch Methoden im Deskriptorprotokoll überschrieben wurde: __get__(), __set__() und __delete__(). Wenn eine dieser Methoden für ein Objekt definiert ist, wird es als Deskriptor bezeichnet.
Das Standardverhalten für den Attributzugriff besteht darin, das Attribut aus dem Wörterbuch eines Objekts zu holen, zu setzen oder zu löschen. Zum Beispiel hat a.x eine Suchkette, die mit a.__dict__['x'] beginnt, dann type(a).__dict__['x'] und weiter durch die Basisklassen von type(a) (ohne Metaklassen) fortfährt.
Wenn der nachgeschlagene Wert jedoch ein Objekt ist, das eine der Deskriptormethoden definiert, kann Python das Standardverhalten überschreiben und stattdessen die Deskriptormethode aufrufen. Wo dies in der Vorrangkette geschieht, hängt davon ab, welche Deskriptormethoden definiert wurden und wie sie aufgerufen wurden.
Der Ausgangspunkt für die Deskriptorinvokation ist eine Bindung, a.x. Wie die Argumente zusammengestellt werden, hängt von a ab
- Direkter Aufruf
Der einfachste und seltenste Aufruf ist, wenn Benutzercode eine Deskriptormethode direkt aufruft:
x.__get__(a).- Instanzbindung
Wenn an eine Objektinstanz gebunden wird, wird
a.xin den Aufruf transformiert:type(a).__dict__['x'].__get__(a, type(a)).- Klassenbindung
Wenn an eine Klasse gebunden wird, wird
A.xin den Aufruf transformiert:A.__dict__['x'].__get__(None, A).- Super-Bindung
Eine punktierte Suche wie
super(A, a).xdurchsuchta.__class__.__mro__nach einer BasisklasseBnachAund gibt dannB.__dict__['x'].__get__(a, A)zurück. Wenn es sich nicht um einen Deskriptor handelt, wirdxunverändert zurückgegeben.
Für Instanzbindungen hängt die Priorität der Deskriptorinvokation davon ab, welche Deskriptormethoden definiert sind. Ein Deskriptor kann jede Kombination von __get__(), __set__() und __delete__() definieren. Wenn es __get__() nicht definiert, gibt der Zugriff auf das Attribut das Deskriptorobjekt selbst zurück, es sei denn, es gibt einen Wert im Instanzwörterbuch des Objekts. Wenn der Deskriptor __set__() und/oder __delete__() definiert, ist es ein Daten-Deskriptor; wenn es keines davon definiert, ist es ein Nicht-Daten-Deskriptor. Normalerweise definieren Daten-Deskriptoren sowohl __get__() als auch __set__(), während Nicht-Daten-Deskriptoren nur die __get__()-Methode haben. Daten-Deskriptoren mit definierten __get__() und __set__() (und/oder __delete__()) überschreiben immer eine Neudefinition in einem Instanzwörterbuch. Im Gegensatz dazu können Nicht-Daten-Deskriptoren durch Instanzen überschrieben werden.
Python-Methoden (einschließlich der mit @staticmethod und @classmethod dekorierten) werden als Nicht-Daten-Deskriptoren implementiert. Daher können Instanzen Methoden neu definieren und überschreiben. Dies ermöglicht es einzelnen Instanzen, Verhaltensweisen zu erwerben, die sich von anderen Instanzen derselben Klasse unterscheiden.
Die Funktion property() wird als Daten-Deskriptor implementiert. Daher können Instanzen das Verhalten einer Eigenschaft nicht überschreiben.
3.3.2.4. __slots__¶
__slots__ erlauben uns, explizit Datenmember (wie Eigenschaften) zu deklarieren und die Erstellung von __dict__ und __weakref__ zu verweigern (es sei denn, sie sind explizit in __slots__ deklariert oder in einem Elternteil verfügbar).
Der Platz, der im Vergleich zur Verwendung von __dict__ gespart wird, kann erheblich sein. Die Geschwindigkeit der Attributsuche kann ebenfalls erheblich verbessert werden.
- object.__slots__¶
Diese Klassenvariable kann einem String, einem iterierbaren Objekt oder einer Sequenz von Strings mit Variablennamen zugewiesen werden, die von Instanzen verwendet werden. __slots__ reserviert Speicher für die deklarierten Variablen und verhindert die automatische Erstellung von
__dict__und __weakref__ für jede Instanz.
Hinweise zur Verwendung von __slots__
Beim Erben von einer Klasse ohne __slots__ sind die Attribute
__dict__und __weakref__ der Instanzen immer zugänglich.Ohne eine
__dict__-Variable können Instanzen keine neuen Variablen zugewiesen werden, die nicht in der __slots__-Definition aufgeführt sind. Versuche, einer nicht aufgelisteten Variablennamen zuzuweisen, lösen eineAttributeErroraus. Wenn eine dynamische Zuweisung neuer Variablen gewünscht ist, fügen Sie'__dict__'zur Sequenz von Strings in der __slots__-Deklaration hinzu.Ohne eine __weakref__-Variable für jede Instanz unterstützen Klassen, die __slots__ definieren, keine
schwachen Referenzenauf ihre Instanzen. Wenn Unterstützung für schwache Referenzen benötigt wird, fügen Sie'__weakref__'zur Sequenz von Strings in der __slots__-Deklaration hinzu.__slots__ werden auf Klassenebene implementiert, indem Deskriptoren für jeden Variablennamen erstellt werden. Daher können Klassenattribute nicht verwendet werden, um Standardwerte für Instanzvariablen festzulegen, die von __slots__ definiert wurden; andernfalls würde das Klassenattribut die Deskriptorzuweisung überschreiben.
Die Aktion einer __slots__-Deklaration beschränkt sich nicht auf die Klasse, in der sie definiert ist. In Elternklassen deklarierte __slots__ sind in Kindklassen verfügbar. Instanzen einer Kindunterklasse erhalten jedoch ein
__dict__und __weakref__, es sei denn, die Unterklasse definiert ebenfalls __slots__ (die nur Namen für *zusätzliche* Slots enthalten sollte).Wenn eine Klasse einen Slot definiert, der bereits in einer Basisklasse definiert ist, ist die Instanzvariable, die vom Basisklassenslot definiert wird, unzugänglich (außer durch direkte Abfrage ihres Deskriptors von der Basisklasse). Dies macht die Bedeutung des Programms undefiniert. In Zukunft kann eine Prüfung hinzugefügt werden, um dies zu verhindern.
Eine
TypeErrorwird ausgelöst, wenn nicht-leere __slots__ für eine Klasse definiert werden, die von einem"variable-length" eingebauten Typwieint,bytesundtupleabgeleitet ist.Jede nicht-String-iterierbare kann __slots__ zugewiesen werden.
Wenn ein
Wörterbuchzur Zuweisung von __slots__ verwendet wird, werden die Wörterbuchschlüssel als Slotnamen verwendet. Die Werte des Wörterbuchs können zur Bereitstellung von Dokumentationsstrings pro Attribut verwendet werden, die voninspect.getdoc()erkannt und in der Ausgabe vonhelp()angezeigt werden.__class__-Zuweisung funktioniert nur, wenn beide Klassen dieselben __slots__ haben.Es kann Mehrfachvererbung mit mehreren Slot-basierten Elternklassen verwendet werden, aber nur ein Elternteil darf Attribute haben, die durch Slots erstellt wurden (die anderen Basen müssen leere Slot-Layouts haben) – Verstöße lösen eine
TypeErroraus.Wenn ein Iterator für __slots__ verwendet wird, wird für jeden Wert des Iterators ein Deskriptor erstellt. Das Attribut __slots__ wird jedoch ein leerer Iterator sein.
3.3.3. Anpassen der Klassenerstellung¶
Immer wenn eine Klasse von einer anderen Klasse erbt, wird __init_subclass__() auf der Elternklasse aufgerufen. Auf diese Weise ist es möglich, Klassen zu schreiben, die das Verhalten von Unterklassen ändern. Dies steht in engem Zusammenhang mit Klassendekoratoren, aber während Klassendekoratoren nur die spezifische Klasse beeinflussen, auf die sie angewendet werden, gilt __init_subclass__ ausschließlich für zukünftige Unterklassen der Klasse, die die Methode definiert.
- classmethod object.__init_subclass__(cls)¶
Diese Methode wird aufgerufen, wenn die enthaltende Klasse unterklassenbildet wird. cls ist dann die neue Unterklasse. Wenn als normale Instanzmethode definiert, wird diese Methode implizit in eine Klassenmethode umgewandelt.
Schlüsselwortargumente, die an eine neue Klasse übergeben werden, werden an die
__init_subclass__der Elternklasse übergeben. Zur Kompatibilität mit anderen Klassen, die__init_subclass__verwenden, sollte man die benötigten Schlüsselwortargumente entnehmen und die anderen an die Basisklasse weitergeben, wie z.B.class Philosopher: def __init_subclass__(cls, /, default_name, **kwargs): super().__init_subclass__(**kwargs) cls.default_name = default_name class AustralianPhilosopher(Philosopher, default_name="Bruce"): pass
Die Standardimplementierung
object.__init_subclass__tut nichts, löst aber einen Fehler aus, wenn sie mit Argumenten aufgerufen wird.Hinweis
Der Metaklassenhinweis
metaclasswird vom Rest der Typen-Maschinerie verarbeitet und niemals an__init_subclass__-Implementierungen übergeben. Die tatsächliche Metaklasse (anstatt des expliziten Hinweises) kann alstype(cls)abgerufen werden.Hinzugefügt in Version 3.6.
Wenn eine Klasse erstellt wird, durchsucht type.__new__() die Klassenvariablen und ruft die mit einem __set_name__-Hook auf.
- object.__set_name__(self, owner, name)¶
Wird automatisch aufgerufen, wenn die Besitzerklasse owner erstellt wird. Das Objekt wurde in dieser Klasse unter name zugewiesen.
class A: x = C() # Automatically calls: x.__set_name__(A, 'x')
Wenn die Klassenvariable nach der Klassenerstellung zugewiesen wird, wird
__set_name__()nicht automatisch aufgerufen. Bei Bedarf kann__set_name__()direkt aufgerufen werden.class A: pass c = C() A.x = c # The hook is not called c.__set_name__(A, 'x') # Manually invoke the hook
Siehe Erstellen des Klassenobjekts für weitere Details.
Hinzugefügt in Version 3.6.
3.3.3.1. Metaklassen¶
Standardmäßig werden Klassen mit type() konstruiert. Der Klassenkörper wird in einem neuen Namensraum ausgeführt und der Klassenname wird lokal an das Ergebnis von type(name, bases, namespace) gebunden.
Der Prozess der Klassenerstellung kann angepasst werden, indem das Schlüsselwortargument metaclass in der Klassendefinitionszeile übergeben wird oder indem von einer vorhandenen Klasse geerbt wird, die ein solches Argument enthielt. Im folgenden Beispiel sind sowohl MyClass als auch MySubclass Instanzen von Meta
class Meta(type):
pass
class MyClass(metaclass=Meta):
pass
class MySubclass(MyClass):
pass
Alle anderen Schlüsselwortargumente, die in der Klassendefinition angegeben sind, werden an alle unten beschriebenen Metaklassenoperationen weitergegeben.
Wenn eine Klassendefinition ausgeführt wird, geschehen folgende Schritte:
MRO-Einträge werden aufgelöst;
die entsprechende Metaklasse wird bestimmt;
der Klassen-Namensraum wird vorbereitet;
der Klassenkörper wird ausgeführt;
das Klassenobjekt wird erstellt.
3.3.3.2. Auflösen von MRO-Einträgen¶
- object.__mro_entries__(self, bases)¶
Wenn eine Basis, die in einer Klassendefinition vorkommt, keine Instanz von
typeist, dann wird eine__mro_entries__()-Methode auf der Basis gesucht. Wenn eine__mro_entries__()-Methode gefunden wird, wird die Basis durch das Ergebnis eines Aufrufs von__mro_entries__()bei der Erstellung der Klasse ersetzt. Die Methode wird mit dem ursprünglichen Basen-Tupel, das dem Parameter bases übergeben wurde, aufgerufen und muss ein Tupel von Klassen zurückgeben, die anstelle der Basis verwendet werden. Das zurückgegebene Tupel kann leer sein: in diesen Fällen wird die ursprüngliche Basis ignoriert.
Siehe auch
types.resolve_bases()Löst dynamisch Basen auf, die keine Instanzen von
typesind.types.get_original_bases()Ruft die "Original-Basen" einer Klasse ab, bevor diese durch
__mro_entries__()modifiziert wurden.- PEP 560
Kernunterstützung für das Modul Typen und generische Typen.
3.3.3.3. Bestimmen der geeigneten Metaklasse¶
Die geeignete Metaklasse für eine Klassendefinition wird wie folgt bestimmt:
Wenn keine Basisklassen und keine explizite Metaklasse angegeben sind, wird
type()verwendet.Wenn eine explizite Metaklasse angegeben ist und diese keine Instanz von
type()ist, wird sie direkt als Metaklasse verwendet.Wenn eine Instanz von
type()als explizite Metaklasse angegeben wird oder Basisklassen definiert sind, wird die am weitesten abgeleitete Metaklasse verwendet.
Die am weitesten abgeleitete Metaklasse wird aus der explizit angegebenen Metaklasse (falls vorhanden) und den Metaklassen (d.h. type(cls)) aller angegebenen Basisklassen ausgewählt. Die am weitesten abgeleitete Metaklasse ist diejenige, die ein Untertyp aller dieser Kandidaten-Metaklassen ist. Wenn keine der Kandidaten-Metaklassen dieses Kriterium erfüllt, schlägt die Klassendefinition mit TypeError fehl.
3.3.3.4. Vorbereitung des Klassen-Namespace¶
Sobald die geeignete Metaklasse identifiziert wurde, wird der Klassen-Namespace vorbereitet. Wenn die Metaklasse ein Attribut __prepare__ hat, wird sie als namespace = metaclass.__prepare__(name, bases, **kwds) aufgerufen (wobei die zusätzlichen Schlüsselwortargumente, falls vorhanden, aus der Klassendefinition stammen). Die Methode __prepare__ sollte als classmethod implementiert werden. Der von __prepare__ zurückgegebene Namespace wird an __new__ übergeben, aber wenn das endgültige Klassenobjekt erstellt wird, wird der Namespace in ein neues dict kopiert.
Wenn die Metaklasse kein Attribut __prepare__ hat, wird der Klassen-Namespace als leeres geordnetes Mapping initialisiert.
Siehe auch
- PEP 3115 - Metaklassen in Python 3000
Führte den Namespace-Hook
__prepare__ein.
3.3.3.5. Ausführung des Klassenkörpers¶
Der Klassenkörper wird (ungefähr) als exec(body, globals(), namespace) ausgeführt. Der Hauptunterschied zu einem normalen Aufruf von exec() besteht darin, dass die lexikalische Geltung (scoping) es dem Klassenkörper (einschließlich aller Methoden) ermöglicht, auf Namen aus dem aktuellen und äußeren Geltungsbereich zuzugreifen, wenn die Klassendefinition innerhalb einer Funktion erfolgt.
Auch wenn die Klassendefinition innerhalb einer Funktion erfolgt, können innerhalb der Klasse definierte Methoden Namen, die im Klassenbereich definiert sind, immer noch nicht sehen. Klassenvariablen müssen über den ersten Parameter von Instanz- oder Klassenmethoden oder über die implizite lexikalisch gültige Referenz __class__, die im nächsten Abschnitt beschrieben wird, aufgerufen werden.
3.3.3.6. Erstellung des Klassenobjekts¶
Nachdem der Klassen-Namespace durch Ausführung des Klassenkörpers gefüllt wurde, wird das Klassenobjekt durch Aufruf von metaclass(name, bases, namespace, **kwds) erstellt (die hier übergebenen zusätzlichen Schlüsselwörter sind dieselben wie die an __prepare__ übergebenen).
Dieses Klassenobjekt ist dasjenige, auf das sich die Null-Argument-Form von super() beziehen wird. __class__ ist eine implizite Closure-Referenz, die vom Compiler erstellt wird, wenn Methoden im Klassenkörper auf entweder __class__ oder super verweisen. Dies ermöglicht es der Null-Argument-Form von super(), die definierte Klasse korrekt zu identifizieren, basierend auf der lexikalischen Geltung, während die Klasse oder Instanz, die für den aktuellen Aufruf verwendet wurde, basierend auf dem ersten an die Methode übergebenen Argument identifiziert wird.
CPython-Implementierungsdetail: In CPython 3.6 und neuer wird die Zelle __class__ als Eintrag __classcell__ im Klassen-Namespace an die Metaklasse übergeben. Falls vorhanden, muss dies an den Aufruf type.__new__ weitergegeben werden, damit die Klasse korrekt initialisiert wird. Wenn dies nicht geschieht, führt dies in Python 3.8 zu einem RuntimeError.
Wenn die Standard-Metaklasse type oder eine Metaklasse, die letztendlich type.__new__ aufruft, verwendet wird, werden nach der Erstellung des Klassenobjekts die folgenden zusätzlichen Anpassungsschritte ausgeführt:
Die Methode
type.__new__sammelt alle Attribute im Klassen-Namespace, die eine Methode__set_name__()definieren;Diese Methoden
__set_name__werden mit der definierten Klasse und dem zugewiesenen Namen dieses speziellen Attributs aufgerufen;Der Hook
__init_subclass__()wird auf dem direkten Elternteil der neuen Klasse in ihrer Methodenauflösungsreihenfolge aufgerufen.
Nachdem das Klassenobjekt erstellt wurde, wird es an die in der Klassendefinition enthaltenen Klassendekoratoren (falls vorhanden) übergeben, und das resultierende Objekt wird im lokalen Namespace als die definierte Klasse gebunden.
Wenn eine neue Klasse von type.__new__ erstellt wird, wird das als Namespace-Parameter bereitgestellte Objekt in ein neues geordnetes Mapping kopiert und das ursprüngliche Objekt verworfen. Die neue Kopie wird in einen schreibgeschützten Proxy eingewickelt, der zum Attribut __dict__ des Klassenobjekts wird.
Siehe auch
- PEP 3135 - Neues super
Beschreibt die implizite Closure-Referenz
__class__.
3.3.3.7. Verwendungen für Metaklassen¶
Die potenziellen Verwendungen für Metaklassen sind grenzenlos. Einige untersuchte Ideen sind Enums, Logging, Schnittstellenprüfung, automatische Delegation, automatische Erstellung von Eigenschaften, Proxys, Frameworks und automatische Ressourcensperrung/-synchronisation.
3.3.4. Anpassen von Instanz- und Unterklassenprüfungen¶
Die folgenden Methoden werden verwendet, um das Standardverhalten der eingebauten Funktionen isinstance() und issubclass() zu überschreiben.
Insbesondere implementiert die Metaklasse abc.ABCMeta diese Methoden, um die Hinzufügung von abstrakten Basisklassen (ABCs) als „virtuelle Basisklassen“ zu jeder Klasse oder jedem Typ (einschließlich integrierter Typen), einschließlich anderer ABCs, zu ermöglichen.
- type.__instancecheck__(self, instance)¶
Gibt true zurück, wenn instance als (direkte oder indirekte) Instanz von class betrachtet werden soll. Wenn definiert, wird es zur Implementierung von
isinstance(instance, class)aufgerufen.
- type.__subclasscheck__(self, subclass)¶
Gibt true zurück, wenn subclass als (direkte oder indirekte) Unterklasse von class betrachtet werden soll. Wenn definiert, wird es zur Implementierung von
issubclass(subclass, class)aufgerufen.
Beachten Sie, dass diese Methoden auf dem Typ (Metaklasse) einer Klasse nachgeschlagen werden. Sie können nicht als Klassenmethoden in der eigentlichen Klasse definiert werden. Dies stimmt mit dem Nachschlagen von Sonder-Methoden überein, die auf Instanzen aufgerufen werden, nur dass in diesem Fall die Instanz selbst eine Klasse ist.
Siehe auch
- PEP 3119 - Einführung von abstrakten Basisklassen
Enthält die Spezifikation für die Anpassung des Verhaltens von
isinstance()undissubclass()durch__instancecheck__()und__subclasscheck__(), mit der Begründung für diese Funktionalität im Kontext der Hinzufügung von abstrakten Basisklassen (siehe Modulabc) zur Sprache.
3.3.5. Emulieren generischer Typen¶
Bei der Verwendung von Typ-Annotationen ist es oft nützlich, einen generischen Typ mithilfe der Square-Bracket-Notation von Python zu parametrisieren. Beispielsweise könnte die Annotation list[int] verwendet werden, um eine list zu bezeichnen, in der alle Elemente vom Typ int sind.
Siehe auch
- PEP 484 - Typ-Hints
Einführung des Python-Frameworks für Typ-Annotationen.
- Generische Alias-Typen
Dokumentation für Objekte, die parametrisierte generische Klassen darstellen.
- Generics, selbst definierte Generics und
typing.Generic Dokumentation zur Implementierung von generischen Klassen, die zur Laufzeit parametrisiert und von statischen Typ-Prüfern verstanden werden können.
Eine Klasse kann im Allgemeinen nur parametrisiert werden, wenn sie die spezielle Klassenmethode __class_getitem__() definiert.
- classmethod object.__class_getitem__(cls, key)¶
Gibt ein Objekt zurück, das die Spezialisierung einer generischen Klasse durch die in key gefundenen Typargumente darstellt.
Wenn
__class_getitem__()auf einer Klasse definiert ist, ist sie automatisch eine Klassenmethode. Daher besteht keine Notwendigkeit, sie mit@classmethodzu dekorieren, wenn sie definiert wird.
3.3.5.1. Der Zweck von __class_getitem__¶
Der Zweck von __class_getitem__() ist die Laufzeitparametrisierung von generischen Standardbibliotheksklassen, um Typ-Hints für diese Klassen leichter anwenden zu können.
Um benutzerdefinierte generische Klassen zu implementieren, die zur Laufzeit parametrisiert und von statischen Typ-Prüfern verstanden werden können, sollten Benutzer entweder von einer Standardbibliotheksklasse erben, die __class_getitem__() bereits implementiert, oder von typing.Generic erben, die eine eigene Implementierung von __class_getitem__() hat.
Benutzerdefinierte Implementierungen von __class_getitem__() auf Klassen, die außerhalb der Standardbibliothek definiert sind, werden möglicherweise nicht von Drittanbieter-Typ-Prüfern wie mypy verstanden. Die Verwendung von __class_getitem__() auf beliebigen Klassen für andere Zwecke als Typ-Hints wird nicht empfohlen.
3.3.5.2. __class_getitem__ versus __getitem__¶
Normalerweise ruft die Subscription eines Objekts mit eckigen Klammern die Instanzmethode __getitem__() auf, die auf der Klasse des Objekts definiert ist. Wenn das zu abonnierende Objekt jedoch selbst eine Klasse ist, kann stattdessen die Klassenmethode __class_getitem__() aufgerufen werden. __class_getitem__() sollte ein GenericAlias-Objekt zurückgeben, wenn es korrekt definiert ist.
Angesichts des Ausdrucks obj[x] folgt der Python-Interpreter ungefähr dem folgenden Prozess, um zu entscheiden, ob __getitem__() oder __class_getitem__() aufgerufen werden soll:
from inspect import isclass
def subscribe(obj, x):
"""Return the result of the expression 'obj[x]'"""
class_of_obj = type(obj)
# If the class of obj defines __getitem__,
# call class_of_obj.__getitem__(obj, x)
if hasattr(class_of_obj, '__getitem__'):
return class_of_obj.__getitem__(obj, x)
# Else, if obj is a class and defines __class_getitem__,
# call obj.__class_getitem__(x)
elif isclass(obj) and hasattr(obj, '__class_getitem__'):
return obj.__class_getitem__(x)
# Else, raise an exception
else:
raise TypeError(
f"'{class_of_obj.__name__}' object is not subscriptable"
)
In Python sind alle Klassen selbst Instanzen anderer Klassen. Die Klasse einer Klasse wird als ihre Metaklasse bezeichnet, und die meisten Klassen haben die Klasse type als ihre Metaklasse. type definiert keine __getitem__(), was bedeutet, dass Ausdrücke wie list[int], dict[str, float] und tuple[str, bytes] alle dazu führen, dass __class_getitem__() aufgerufen wird.
>>> # list has class "type" as its metaclass, like most classes:
>>> type(list)
<class 'type'>
>>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes)
True
>>> # "list[int]" calls "list.__class_getitem__(int)"
>>> list[int]
list[int]
>>> # list.__class_getitem__ returns a GenericAlias object:
>>> type(list[int])
<class 'types.GenericAlias'>
Wenn eine Klasse jedoch eine benutzerdefinierte Metaklasse hat, die __getitem__() definiert, kann die Subscription der Klasse zu einem anderen Verhalten führen. Ein Beispiel dafür findet sich im Modul enum.
>>> from enum import Enum
>>> class Menu(Enum):
... """A breakfast menu"""
... SPAM = 'spam'
... BACON = 'bacon'
...
>>> # Enum classes have a custom metaclass:
>>> type(Menu)
<class 'enum.EnumMeta'>
>>> # EnumMeta defines __getitem__,
>>> # so __class_getitem__ is not called,
>>> # and the result is not a GenericAlias object:
>>> Menu['SPAM']
<Menu.SPAM: 'spam'>
>>> type(Menu['SPAM'])
<enum 'Menu'>
Siehe auch
- PEP 560 - Kernunterstützung für das typing-Modul und generische Typen
Einführung von
__class_getitem__()und Beschreibung, wann eine Subscription dazu führt, dass__class_getitem__()anstelle von__getitem__()aufgerufen wird.
3.3.6. Emulieren von aufrufbaren Objekten¶
- object.__call__(self[, args...])¶
Wird aufgerufen, wenn die Instanz wie eine Funktion „aufgerufen“ wird; wenn diese Methode definiert ist, wird
x(arg1, arg2, ...)ungefähr zutype(x).__call__(x, arg1, ...).
3.3.7. Emulieren von Container-Objekten¶
Die folgenden Methoden können definiert werden, um Container-Objekte zu implementieren. Keine davon wird von der Klasse object selbst bereitgestellt. Container sind normalerweise Sequenzen (wie Listen oder Tupel) oder Mappings (wie Dictionaries), können aber auch andere Container darstellen. Die erste Gruppe von Methoden wird verwendet, um entweder eine Sequenz oder ein Mapping zu emulieren; der Unterschied besteht darin, dass für eine Sequenz die erlaubten Schlüssel die ganzen Zahlen k sind, für die 0 <= k < N gilt, wobei N die Länge der Sequenz ist, oder slice-Objekte, die einen Bereich von Elementen definieren. Es wird auch empfohlen, dass Mappings die Methoden keys(), values(), items(), get(), clear(), setdefault(), pop(), popitem(), copy() und update() bereitstellen, die sich ähnlich wie die für die Standard- Dictionary-Objekte von Python verhalten. Das Modul collections.abc stellt eine MutableMapping abstrakte Basisklasse zur Verfügung, um diese Methoden aus einem Basissatz von __getitem__(), __setitem__(), __delitem__() und keys() zu erstellen.
Mutable Sequenzen sollten die Methoden append(), clear(), count(), extend(), index(), insert(), pop(), remove() und reverse() bereitstellen, wie Python-Standard- Listen-Objekte. Schließlich sollten Sequenztypen Addition (d. h. Verkettung) und Multiplikation (d. h. Wiederholung) durch Definition der unten beschriebenen Methoden __add__(), __radd__(), __iadd__(), __mul__(), __rmul__() und __imul__() implementieren; sie sollten keine anderen numerischen Operatoren definieren.
Es wird empfohlen, dass sowohl Mappings als auch Sequenzen die Methode __contains__() implementieren, um eine effiziente Nutzung des in-Operators zu ermöglichen; für Mappings sollte in die Schlüssel des Mappings durchsuchen; für Sequenzen sollte es die Werte durchsuchen. Weiterhin wird empfohlen, dass sowohl Mappings als auch Sequenzen die Methode __iter__() implementieren, um eine effiziente Iteration durch den Container zu ermöglichen; für Mappings sollte __iter__() die Schlüssel des Objekts durchlaufen; für Sequenzen sollte es die Werte durchlaufen.
- object.__len__(self)¶
Wird aufgerufen, um die eingebaute Funktion
len()zu implementieren. Sollte die Länge des Objekts zurückgeben, eine Ganzzahl>= 0. Ein Objekt, das keine Methode__bool__()definiert und dessen Methode__len__()null zurückgibt, wird in einem booleschen Kontext als falsch betrachtet.CPython-Implementierungsdetail: In CPython muss die Länge höchstens
sys.maxsizebetragen. Wenn die Länge größer alssys.maxsizeist, können einige Funktionen (wielen()) einenOverflowErrorauslösen. Um die Auslösung einesOverflowErrordurch boolesche Wertprüfung zu vermeiden, muss ein Objekt eine Methode__bool__()definieren.
- object.__length_hint__(self)¶
Wird aufgerufen, um
operator.length_hint()zu implementieren. Soll eine geschätzte Länge für das Objekt zurückgeben (die größer oder kleiner als die tatsächliche Länge sein kann). Die Länge muss eine Ganzzahl >= 0 sein. Der Rückgabewert kann auchNotImplementedsein, was genauso behandelt wird, als ob die Methode__length_hint__gar nicht existieren würde. Diese Methode dient ausschließlich der Optimierung und ist für die Korrektheit niemals erforderlich.Hinzugefügt in Version 3.4.
Hinweis
Das Slicing erfolgt ausschließlich mit den folgenden drei Methoden. Ein Aufruf wie
a[1:2] = b
wird übersetzt zu
a[slice(1, 2, None)] = b
und so weiter. Fehlende Slice-Elemente werden immer mit None gefüllt.
- object.__getitem__(self, key)¶
Wird aufgerufen, um die Auswertung von
self[key]zu implementieren. Für Sequenz-Typen sollten die akzeptierten Schlüssel Ganzzahlen sein. Optional können sie auchslice-Objekte unterstützen. Negative Indexunterstützung ist ebenfalls optional. Wenn key von einem unangemessenen Typ ist, kannTypeErrorausgelöst werden; wenn key ein Wert außerhalb der Menge der Indizes für die Sequenz ist (nach jeder Sonderinterpretation negativer Werte), sollteIndexErrorausgelöst werden. Für Mapping-Typen sollteKeyErrorausgelöst werden, wenn key fehlt (nicht im Container vorhanden ist).Hinweis
forSchleifen erwarten, dass für ungültige Indizes einIndexErrorausgelöst wird, um die korrekte Erkennung des Endes der Sequenz zu ermöglichen.Hinweis
Beim Subskription einer Klasse kann die spezielle Klassenmethode
__class_getitem__()anstelle von__getitem__()aufgerufen werden. Weitere Einzelheiten finden Sie unter __class_getitem__ im Vergleich zu __getitem__.
- object.__setitem__(self, key, value)¶
Wird aufgerufen, um Zuweisungen zu
self[key]zu implementieren. Gleicher Hinweis wie für__getitem__(). Dies sollte nur für Mappings implementiert werden, wenn die Objekte Änderungen an den Werten für Schlüssel unterstützen oder neue Schlüssel hinzugefügt werden können, oder für Sequenzen, wenn Elemente ersetzt werden können. Für unzulässige key-Werte sollten dieselben Ausnahmen ausgelöst werden wie für die Methode__getitem__().
- object.__delitem__(self, key)¶
Wird aufgerufen, um die Löschung von
self[key]zu implementieren. Gleicher Hinweis wie für__getitem__(). Dies sollte nur für Mappings implementiert werden, wenn die Objekte das Entfernen von Schlüsseln unterstützen, oder für Sequenzen, wenn Elemente aus der Sequenz entfernt werden können. Für unzulässige key-Werte sollten dieselben Ausnahmen ausgelöst werden wie für die Methode__getitem__().
- object.__missing__(self, key)¶
Wird von
dict.__getitem__()aufgerufen, umself[key]für dict-Subklassen zu implementieren, wenn der Schlüssel nicht im Dictionary vorhanden ist.
- object.__iter__(self)¶
Diese Methode wird aufgerufen, wenn ein Iterator für einen Container benötigt wird. Diese Methode sollte ein neues Iteratorobjekt zurückgeben, das über alle Objekte im Container iterieren kann. Für Mappings sollte es über die Schlüssel des Containers iterieren.
- object.__reversed__(self)¶
Wird (falls vorhanden) von der integrierten Funktion
reversed()aufgerufen, um die umgekehrte Iteration zu implementieren. Sie sollte ein neues Iteratorobjekt zurückgeben, das über alle Objekte im Container in umgekehrter Reihenfolge iteriert.Wenn die Methode
__reversed__()nicht bereitgestellt wird, greift die integrierte Funktionreversed()auf das Sequenzprotokoll (__len__()und__getitem__()) zurück. Objekte, die das Sequenzprotokoll unterstützen, sollten__reversed__()nur dann bereitstellen, wenn sie eine Implementierung anbieten können, die effizienter ist als die vonreversed().
Die Membership-Test-Operatoren (in und not in) werden normalerweise als Iteration durch einen Container implementiert. Container-Objekte können jedoch die folgende spezielle Methode mit einer effizienteren Implementierung bereitstellen, die auch nicht erfordert, dass das Objekt iterierbar ist.
- object.__contains__(self, item)¶
Wird aufgerufen, um Membership-Test-Operatoren zu implementieren. Sollte `true` zurückgeben, wenn item in self ist, andernfalls `false`. Für Mapping-Objekte sollte dies die Schlüssel des Mappings berücksichtigen, nicht die Werte oder Schlüssel-Element-Paare.
Für Objekte, die
__contains__()nicht definieren, versucht der Membership-Test zuerst eine Iteration über__iter__()und dann das alte Sequenz-Iterationsprotokoll über__getitem__(), siehe diesen Abschnitt in der Sprachreferenz.
3.3.8. Emulieren numerischer Typen¶
Die folgenden Methoden können definiert werden, um numerische Objekte zu emulieren. Methoden, die Operationen entsprechen, die von der implementierten Zahl nicht unterstützt werden (z. B. bitweise Operationen für nicht-ganzzahlige Zahlen), sollten undefiniert bleiben.
- object.__add__(self, other)¶
- object.__sub__(self, other)¶
- object.__mul__(self, other)¶
- object.__matmul__(self, other)¶
- object.__truediv__(self, other)¶
- object.__floordiv__(self, other)¶
- object.__mod__(self, other)¶
- object.__divmod__(self, other)¶
- object.__pow__(self, other[, modulo])¶
- object.__lshift__(self, other)¶
- object.__rshift__(self, other)¶
- object.__and__(self, other)¶
- object.__xor__(self, other)¶
- object.__or__(self, other)¶
Diese Methoden werden aufgerufen, um die binären arithmetischen Operationen (
+,-,*,@,/,//,%,divmod(),pow(),**,<<,>>,&,^,|) zu implementieren. Zum Beispiel wird zur Auswertung des Ausdrucksx + y, wobei x eine Instanz einer Klasse ist, die eine Methode__add__()hat,type(x).__add__(x, y)aufgerufen. Die Methode__divmod__()sollte dem Gebrauch von__floordiv__()und__mod__()entsprechen; sie sollte nicht mit__truediv__()zusammenhängen. Beachten Sie, dass__pow__()einen optionalen dritten Parameter akzeptieren sollte, wenn die dreistellige Version der integrierten Funktionpow()unterstützt werden soll.Wenn eine dieser Methoden die Operation mit den übergebenen Argumenten nicht unterstützt, sollte sie
NotImplementedzurückgeben.
- object.__radd__(self, other)¶
- object.__rsub__(self, other)¶
- object.__rmul__(self, other)¶
- object.__rmatmul__(self, other)¶
- object.__rtruediv__(self, other)¶
- object.__rfloordiv__(self, other)¶
- object.__rmod__(self, other)¶
- object.__rdivmod__(self, other)¶
- object.__rpow__(self, other[, modulo])¶
- object.__rlshift__(self, other)¶
- object.__rrshift__(self, other)¶
- object.__rand__(self, other)¶
- object.__rxor__(self, other)¶
- object.__ror__(self, other)¶
Diese Methoden werden aufgerufen, um die binären arithmetischen Operationen (
+,-,*,@,/,//,%,divmod(),pow(),**,<<,>>,&,^,|) mit reflektierten (vertauschten) Operanden zu implementieren. Diese Funktionen werden nur aufgerufen, wenn die Operanden unterschiedliche Typen haben, wenn der linke Operand die entsprechende Operation nicht unterstützt [3] oder wenn die Klasse des rechten Operanden von der Klasse des linken Operanden abgeleitet ist [4]. Zum Beispiel wird zur Auswertung des Ausdrucksx - y, wobei y eine Instanz einer Klasse ist, die eine Methode__rsub__()hat,type(y).__rsub__(y, x)aufgerufen, wenntype(x).__sub__(x, y)NotImplementedzurückgibt odertype(y)eine Unterklasse vontype(x)ist [5].Beachten Sie, dass
__rpow__()einen optionalen dritten Parameter akzeptieren sollte, wenn die dreistellige Version der integrierten Funktionpow()unterstützt werden soll.Geändert in Version 3.14: Die dreistellige Funktion
pow()versucht nun,__rpow__()aufzurufen, falls erforderlich. Zuvor wurde sie nur in der zweistelligen Funktionpow()und im binären Potenzoperator aufgerufen.Hinweis
Wenn der Typ des rechten Operanden eine Unterklasse des Typs des linken Operanden ist und diese Unterklasse eine andere Implementierung der reflektierten Methode für die Operation bereitstellt, wird diese Methode aufgerufen, bevor die nicht-reflektierte Methode des linken Operanden aufgerufen wird. Dieses Verhalten ermöglicht es Unterklassen, die Operationen ihrer Vorfahren zu überschreiben.
- object.__iadd__(self, other)¶
- object.__isub__(self, other)¶
- object.__imul__(self, other)¶
- object.__imatmul__(self, other)¶
- object.__itruediv__(self, other)¶
- object.__ifloordiv__(self, other)¶
- object.__imod__(self, other)¶
- object.__ipow__(self, other[, modulo])¶
- object.__ilshift__(self, other)¶
- object.__irshift__(self, other)¶
- object.__iand__(self, other)¶
- object.__ixor__(self, other)¶
- object.__ior__(self, other)¶
Diese Methoden werden aufgerufen, um die augmentierten arithmetischen Zuweisungen zu implementieren (
+=,-=,*=,@=,/=,//=,%=,**=,<<=,>>=,&=,^=,|=). Diese Methoden sollten versuchen, die Operation direkt durchzuführen (indem self modifiziert wird) und das Ergebnis zurückzugeben (was self sein kann, aber nicht muss). Wenn eine bestimmte Methode nicht definiert ist oder wenn diese MethodeNotImplementedzurückgibt, greift die augmentierte Zuweisung auf die normalen Methoden zurück. Wenn beispielsweise x eine Instanz einer Klasse mit einer__iadd__()-Methode ist, istx += yäquivalent zux = x.__iadd__(y). Wenn__iadd__()nicht existiert oder wennx.__iadd__(y)NotImplementedzurückgibt, werdenx.__add__(y)undy.__radd__(x)berücksichtigt, wie bei der Auswertung vonx + y. In bestimmten Situationen kann die augmentierte Zuweisung zu unerwarteten Fehlern führen (siehe Warum löst a_tuple[i] += ['item'] eine Ausnahme aus, wenn die Addition funktioniert?), aber dieses Verhalten ist tatsächlich Teil des Datenmodells.
- object.__neg__(self)¶
- object.__pos__(self)¶
- object.__abs__(self)¶
- object.__invert__(self)¶
Aufgerufen, um die unären arithmetischen Operationen zu implementieren (
-,+,abs()und~).
- object.__complex__(self)¶
- object.__int__(self)¶
- object.__float__(self)¶
Aufgerufen, um die eingebauten Funktionen
complex(),int()undfloat()zu implementieren. Sollte einen Wert vom entsprechenden Typ zurückgeben.
- object.__index__(self)¶
Aufgerufen, um
operator.index()zu implementieren und immer dann, wenn Python benötigt, das numerische Objekt verlustfrei in ein ganzzahliges Objekt zu konvertieren (wie z. B. beim Slicing oder in den eingebauten Funktionenbin(),hex()undoct()). Das Vorhandensein dieser Methode zeigt an, dass das numerische Objekt ein ganzzahliger Typ ist. Muss eine Ganzzahl zurückgeben.Wenn
__int__(),__float__()und__complex__()nicht definiert sind, greifen die entsprechenden eingebauten Funktionenint(),float()undcomplex()auf__index__()zurück.
- object.__round__(self[, ndigits])¶
- object.__trunc__(self)¶
- object.__floor__(self)¶
- object.__ceil__(self)¶
Aufgerufen, um die eingebaute Funktion
round()und diemath-Funktionentrunc(),floor()undceil()zu implementieren. Sofern ndigits nicht an__round__()übergeben wird, sollten alle diese Methoden den auf einenIntegral(typischerweise eineint) gekürzten Wert des Objekts zurückgeben.Geändert in Version 3.14:
int()delegiert nicht mehr an die Methode__trunc__().
3.3.9. With Statement Context Managers¶
Ein Kontextmanager ist ein Objekt, das den Laufzeitkontext definiert, der beim Ausführen einer with-Anweisung eingerichtet werden soll. Der Kontextmanager kümmert sich um den Eintritt in und den Austritt aus dem gewünschten Laufzeitkontext für die Ausführung des Codeblocks. Kontextmanager werden normalerweise über die with-Anweisung aufgerufen (siehe Abschnitt Die with-Anweisung), können aber auch durch direktes Aufrufen ihrer Methoden verwendet werden.
Typische Anwendungsfälle für Kontextmanager sind das Speichern und Wiederherstellen verschiedener Arten von globalem Zustand, das Sperren und Entsperren von Ressourcen, das Schließen geöffneter Dateien usw.
Weitere Informationen zu Kontextmanagern finden Sie unter Context Manager Types. Die Klasse object selbst stellt keine Kontextmanager-Methoden bereit.
- object.__enter__(self)¶
Betritt den Laufzeitkontext, der mit diesem Objekt verbunden ist. Die
with-Anweisung bindet den Rückgabewert dieser Methode an das/die Ziel(e), das/die in deras-Klausel der Anweisung angegeben ist/sind, falls vorhanden.
- object.__exit__(self, exc_type, exc_value, traceback)¶
Verlässt den Laufzeitkontext, der mit diesem Objekt verbunden ist. Die Parameter beschreiben die Ausnahme, die zum Verlassen des Kontexts geführt hat. Wenn der Kontext ohne Ausnahme verlassen wurde, sind alle drei Argumente
None.Wenn eine Ausnahme übergeben wird und die Methode die Ausnahme unterdrücken möchte (d.h. verhindern, dass sie weitergegeben wird), sollte sie einen wahren Wert zurückgeben. Andernfalls wird die Ausnahme nach dem Verlassen dieser Methode normal verarbeitet.
Beachten Sie, dass
__exit__()-Methoden die übergebene Ausnahme nicht erneut auslösen sollten; dies liegt in der Verantwortung des Aufrufers.
3.3.10. Anpassen von Positionsargumenten in der Klassenmustererkennung¶
Wenn ein Klassenname in einem Muster verwendet wird, sind Positionsargumente im Muster standardmäßig nicht erlaubt, d.h. case MyClass(x, y) ist normalerweise ungültig, es sei denn, MyClass unterstützt dies speziell. Um diese Art von Muster verwenden zu können, muss die Klasse ein __match_args__-Attribut definieren.
- object.__match_args__¶
Diese Klassenvariable kann mit einem Tupel von Zeichenketten zugewiesen werden. Wenn diese Klasse in einem Klassenmuster mit Positionsargumenten verwendet wird, wird jedes Positionsargument in ein Schlüsselwortargument umgewandelt, wobei der entsprechende Wert in __match_args__ als Schlüssel verwendet wird. Das Fehlen dieses Attributs entspricht dessen Zuweisung zu
().
Wenn beispielsweise MyClass.__match_args__ gleich ("left", "center", "right") ist, bedeutet dies, dass case MyClass(x, y) äquivalent zu case MyClass(left=x, center=y) ist. Beachten Sie, dass die Anzahl der Argumente im Muster kleiner oder gleich der Anzahl der Elemente in __match_args__ sein muss; wenn sie größer ist, löst der Musterabgleichsversuch eine TypeError aus.
Hinzugefügt in Version 3.10.
Siehe auch
- PEP 634 - Strukturierte Mustererkennung
Die Spezifikation für die Python
match-Anweisung.
3.3.11. Emulation von Puffertypen¶
Das Pufferprotokoll bietet eine Möglichkeit, Python-Objekten effizienten Zugriff auf ein Low-Level-Speicherarray zu ermöglichen. Dieses Protokoll wird von eingebauten Typen wie bytes und memoryview implementiert, und Drittanbieterbibliotheken können zusätzliche Puffertypen definieren.
Obwohl Puffertypen normalerweise in C implementiert werden, ist es auch möglich, das Protokoll in Python zu implementieren.
- object.__buffer__(self, flags)¶
Wird aufgerufen, wenn ein Puffer von self angefordert wird (z. B. vom Konstruktor
memoryview). Das Argument flags ist eine Ganzzahl, die die Art des angeforderten Puffers darstellt und z. B. beeinflusst, ob der zurückgegebene Puffer schreibgeschützt oder beschreibbar ist.inspect.BufferFlagsbietet eine bequeme Möglichkeit, die Flags zu interpretieren. Die Methode muss einmemoryview-Objekt zurückgeben.
- object.__release_buffer__(self, buffer)¶
Wird aufgerufen, wenn ein Puffer nicht mehr benötigt wird. Das Argument buffer ist ein
memoryview-Objekt, das zuvor von__buffer__()zurückgegeben wurde. Die Methode muss alle mit dem Puffer verbundenen Ressourcen freigeben. Diese Methode sollteNonezurückgeben. Pufferobjekte, die keine Bereinigungsarbeiten durchführen müssen, müssen diese Methode nicht implementieren.
Hinzugefügt in Version 3.12.
Siehe auch
- PEP 688 - Zugänglichmachung des Pufferprotokolls in Python
Führt die Python-Methoden
__buffer__und__release_buffer__ein.collections.abc.BufferABC für Puffertypen.
3.3.12. Annotationen¶
Funktionen, Klassen und Module können Annotationen enthalten, die eine Möglichkeit darstellen, Informationen (typischerweise Typ-Hints) mit einem Symbol zu verknüpfen.
- object.__annotations__¶
Dieses Attribut enthält die Annotationen für ein Objekt. Es wird verzögert ausgewertet, sodass der Zugriff auf das Attribut beliebigen Code ausführen und Ausnahmen auslösen kann. Wenn die Auswertung erfolgreich ist, wird das Attribut auf ein Wörterbuch gesetzt, das Variablennamen auf Annotationen abbildet.
Geändert in Version 3.14: Annotationen werden jetzt verzögert ausgewertet.
- object.__annotate__(format)¶
Eine Annotate-Funktion. Gibt ein neues Wörterbuchobjekt zurück, das Attribut-/Parameter-Namen auf ihre Annotationswerte abbildet.
Nimmt einen Formatparameter entgegen, der das Format angibt, in dem Annotationswerte bereitgestellt werden sollen. Es muss ein Mitglied des Enums
annotationlib.Formatoder eine Ganzzahl mit einem Wert sein, der einem Mitglied des Enums entspricht.Wenn eine Annotate-Funktion das angeforderte Format nicht unterstützt, muss sie
NotImplementedErrorauslösen. Annotate-Funktionen müssen immer dasVALUE-Format unterstützen; sie dürfen keineNotImplementedError()auslösen, wenn sie mit diesem Format aufgerufen werden.Wenn sie mit dem
VALUE-Format aufgerufen wird, kann eine Annotate-FunktionNameErrorauslösen; sie darf keinenNameErrorauslösen, wenn sie ein anderes Format anfordert.Wenn ein Objekt keine Annotationen hat, sollte
__annotate__vorzugsweise aufNonegesetzt werden (es kann nicht gelöscht werden), anstatt auf eine Funktion gesetzt zu werden, die ein leeres Wörterbuch zurückgibt.Hinzugefügt in Version 3.14.
Siehe auch
- PEP 649 – Verzögerte Auswertung von Annotationen mittels Deskriptoren
Führt die verzögerte Auswertung von Annotationen und die Funktion
__annotate__ein.
3.3.13. Suche nach speziellen Methoden¶
Bei benutzerdefinierten Klassen sind implizite Aufrufe spezieller Methoden nur dann garantiert korrekt, wenn sie auf dem Typ eines Objekts definiert sind und nicht im Instanzwörterbuch des Objekts. Dieses Verhalten ist der Grund, warum der folgende Code eine Ausnahme auslöst
>>> class C:
... pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()
Der Grund für dieses Verhalten liegt in einer Reihe von speziellen Methoden wie __hash__() und __repr__(), die von allen Objekten, einschließlich Typobjekten, implementiert werden. Wenn die implizite Suche nach diesen Methoden den konventionellen Suchprozess verwenden würde, würden sie fehlschlagen, wenn sie auf dem Typobjekt selbst aufgerufen werden.
>>> 1 .__hash__() == hash(1)
True
>>> int.__hash__() == hash(int)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument
Der falsch versuchte Aufruf einer ungebundenen Methode einer Klasse auf diese Weise wird manchmal als „Metaklassenverwirrung“ bezeichnet und wird vermieden, indem die Instanz bei der Suche nach speziellen Methoden umgangen wird.
>>> type(1).__hash__(1) == hash(1)
True
>>> type(int).__hash__(int) == hash(int)
True
Zusätzlich zum Umgehen von Instanzattributen im Interesse der Korrektheit umgeht die implizite Suche nach speziellen Methoden im Allgemeinen auch die Methode __getattribute__(), selbst die des Metatyps des Objekts.
>>> class Meta(type):
... def __getattribute__(*args):
... print("Metaclass getattribute invoked")
... return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print("Class getattribute invoked")
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
Das Umgehen der __getattribute__()-Mechanismen in dieser Weise bietet erhebliche Möglichkeiten für Geschwindigkeitsoptimierungen innerhalb des Interpreters, auf Kosten einiger Flexibilität bei der Handhabung spezieller Methoden (die spezielle Methode *muss* auf dem Klassenobjekt selbst gesetzt werden, um vom Interpreter konsistent aufgerufen zu werden).
3.4. Coroutinen¶
3.4.1. Awaitable Objects¶
Ein awaitable-Objekt implementiert im Allgemeinen eine __await__()-Methode. Coroutine-Objekte, die von async def-Funktionen zurückgegeben werden, sind awaitable.
Hinweis
Die Generator-Iterator-Objekte, die von Generatoren zurückgegeben werden, die mit types.coroutine() dekoriert sind, sind ebenfalls awaitable, aber sie implementieren keine __await__().
- object.__await__(self)¶
Muss einen Iterator zurückgeben. Sollte zur Implementierung von awaitable-Objekten verwendet werden. Zum Beispiel implementiert
asyncio.Futurediese Methode, um mit demawait-Ausdruck kompatibel zu sein. Die Klasseobjectselbst ist nicht awaitable und stellt diese Methode nicht bereit.
Hinzugefügt in Version 3.5.
Siehe auch
PEP 492 für zusätzliche Informationen über awaitable-Objekte.
3.4.2. Coroutine Objects¶
Coroutine-Objekte sind awaitable-Objekte. Die Ausführung einer Coroutine kann gesteuert werden, indem __await__() aufgerufen und das Ergebnis iteriert wird. Wenn die Coroutine ihre Ausführung beendet und zurückkehrt, löst der Iterator StopIteration aus, und das Attribut value der Ausnahme enthält den Rückgabewert. Wenn die Coroutine eine Ausnahme auslöst, wird diese vom Iterator propagiert. Coroutinen sollten keine unbehandelten StopIteration-Ausnahmen direkt auslösen.
Coroutinen haben auch die unten aufgeführten Methoden, die analog zu denen von Generatoren sind (siehe Generator-Iterator-Methoden). Im Gegensatz zu Generatoren unterstützen Coroutinen jedoch keine direkte Iteration.
Geändert in Version 3.5.2: Es ist ein RuntimeError, eine Coroutine mehr als einmal zu awaiten.
- coroutine.send(value)¶
Startet oder setzt die Ausführung der Coroutine fort. Wenn value
Noneist, entspricht dies dem Vorschieben des von__await__()zurückgegebenen Iterators. Wenn value nichtNoneist, delegiert diese Methode an diesend()-Methode des Iterators, der die Coroutine zum Anhalten gebracht hat. Das Ergebnis (Rückgabewert,StopIterationoder eine andere Ausnahme) ist dasselbe wie beim Iterieren über den Rückgabewert von__await__(), wie oben beschrieben.
- coroutine.throw(value)¶
- coroutine.throw(type[, value[, traceback]])
Löst die angegebene Ausnahme in der Coroutine aus. Diese Methode delegiert an die
throw()-Methode des Iterators, der die Coroutine zum Anhalten gebracht hat, falls dieser eine solche Methode besitzt. Andernfalls wird die Ausnahme an der Anhaltestelle ausgelöst. Das Ergebnis (Rückgabewert,StopIterationoder eine andere Ausnahme) ist dasselbe wie beim Iterieren über den Rückgabewert von__await__(), wie oben beschrieben. Wenn die Ausnahme in der Coroutine nicht abgefangen wird, propagiert sie zurück zum Aufrufer.Geändert in Version 3.12: Die zweite Signatur (type[, value[, traceback]]) ist veraltet und wird möglicherweise in einer zukünftigen Python-Version entfernt.
- coroutine.close()¶
Veranlasst die Coroutine, sich selbst aufzuräumen und zu beenden. Wenn die Coroutine angehalten ist, delegiert diese Methode zuerst an die
close()-Methode des Iterators, der die Coroutine zum Anhalten gebracht hat, falls dieser eine solche Methode besitzt. Dann löst sieGeneratorExitan der Anhaltestelle aus, was dazu führt, dass sich die Coroutine sofort selbst aufräumt. Schließlich wird die Coroutine als beendet markiert, auch wenn sie nie gestartet wurde.Coroutine-Objekte werden automatisch mit dem obigen Verfahren geschlossen, wenn sie zerstört werden.
3.4.3. Asynchronous Iterators¶
Ein asynchroner Iterator kann asynchronen Code in seiner __anext__-Methode aufrufen.
Asynchrone Iteratoren können in einer async for-Anweisung verwendet werden.
Die object-Klasse selbst stellt diese Methoden nicht bereit.
- object.__aiter__(self)¶
Muss ein asynchrones Iterator-Objekt zurückgeben.
- object.__anext__(self)¶
Muss ein awaitable zurückgeben, das zu einem nächsten Wert des Iterators aufgelöst wird. Sollte eine
StopAsyncIteration-Ausnahme auslösen, wenn die Iteration beendet ist.
Ein Beispiel für ein asynchrones iterierbares Objekt
class Reader:
async def readline(self):
...
def __aiter__(self):
return self
async def __anext__(self):
val = await self.readline()
if val == b'':
raise StopAsyncIteration
return val
Hinzugefügt in Version 3.5.
Geändert in Version 3.7: Vor Python 3.7 konnte __aiter__() ein awaitable zurückgeben, das zu einem asynchronen Iterator aufgelöst wurde.
Ab Python 3.7 muss __aiter__() ein asynchrones Iterator-Objekt zurückgeben. Die Rückgabe von etwas anderem führt zu einer TypeError-Ausnahme.
3.4.4. Asynchrone Kontextmanager¶
Ein asynchroner Kontextmanager ist ein Kontextmanager, der die Ausführung in seinen __aenter__- und __aexit__-Methoden unterbrechen kann.
Asynchrone Kontextmanager können in einer async with-Anweisung verwendet werden.
Die object-Klasse selbst stellt diese Methoden nicht bereit.
- object.__aenter__(self)¶
Semantisch ähnlich zu
__enter__(), der einzige Unterschied ist, dass es ein awaitable zurückgeben muss.
- object.__aexit__(self, exc_type, exc_value, traceback)¶
Semantisch ähnlich zu
__exit__(), der einzige Unterschied ist, dass es ein awaitable zurückgeben muss.
Ein Beispiel für eine asynchrone Kontextmanagerklasse
class AsyncContextManager:
async def __aenter__(self):
await log('entering context')
async def __aexit__(self, exc_type, exc, tb):
await log('exiting context')
Hinzugefügt in Version 3.5.
Fußnoten