8. Zusammengesetzte Anweisungen¶
Zusammengesetzte Anweisungen enthalten (Gruppen von) anderen Anweisungen; sie beeinflussen oder steuern in gewisser Weise die Ausführung dieser anderen Anweisungen. Im Allgemeinen erstrecken sich zusammengesetzte Anweisungen über mehrere Zeilen, obwohl in einfachen Fällen eine gesamte zusammengesetzte Anweisung auch in einer einzigen Zeile enthalten sein kann.
Die Anweisungen if, while und for implementieren traditionelle Kontrollflusskonstrukte. try legt Ausnahmebehandler und/oder Aufräumcode für eine Gruppe von Anweisungen fest, während die Anweisung with die Ausführung von Initialisierungs- und Finalisierungscode um einen Codeblock herum ermöglicht. Funktions- und Klassendefinitionen sind syntaktisch ebenfalls zusammengesetzte Anweisungen.
Eine zusammengesetzte Anweisung besteht aus einer oder mehreren „Klauseln“. Eine Klausel besteht aus einer Überschrift und einer „Suite“. Die Klauselüberschriften einer bestimmten zusammengesetzten Anweisung befinden sich alle auf derselben Einrückungsebene. Jede Klauselüberschrift beginnt mit einem eindeutig identifizierenden Schlüsselwort und endet mit einem Doppelpunkt. Eine Suite ist eine Gruppe von Anweisungen, die von einer Klausel gesteuert werden. Eine Suite kann aus einer oder mehreren durch Semikolons getrennten einfachen Anweisungen bestehen, die sich in derselben Zeile wie die Überschrift befinden und auf den Doppelpunkt der Überschrift folgen, oder aus einer oder mehreren eingerückten Anweisungen in den folgenden Zeilen. Nur die letztgenannte Form einer Suite darf verschachtelte zusammengesetzte Anweisungen enthalten; das folgende Beispiel ist unzulässig, vor allem weil unklar wäre, zu welcher if -Klausel eine nachfolgende else -Klausel gehören würde:
if test1: if test2: print(x)
Beachten Sie außerdem, dass das Semikolon in diesem Zusammenhang eine stärkere Bindung hat als der Doppelpunkt, sodass im folgenden Beispiel entweder alle oder gar keine der print() -Aufrufe ausgeführt werden:
Wenn x < y < z: print(x); print(y); print(z)
Zusammenfassend lässt sich sagen:
compound_stmt ::=if_stmt|while_stmt|for_stmt|try_stmt|with_stmt|match_stmt|funcdef|classdef|async_with_stmt|async_for_stmt|async_funcdefsuite ::=stmt_listNEWLINE | NEWLINE INDENTstatement+ DEDENT statement ::=stmt_listNEWLINE |compound_stmtstmt_list ::=simple_stmt(";"simple_stmt)* [";"]
Beachten Sie, dass Anweisungen immer mit einem NEWLINE enden, auf das möglicherweise ein DEDENT folgt. Beachten Sie außerdem, dass optionale Fortsetzungsklauseln immer mit einem Schlüsselwort beginnen, das keine Anweisung einleiten darf, sodass keine Mehrdeutigkeiten entstehen (das Problem der dangling else wird in Python dadurch gelöst, dass verschachtelte if -Anweisungen eingerückt sein müssen).
Zur besseren Übersichtlichkeit werden die Grammatikregeln in den folgenden Abschnitten so formatiert, dass jeder Satzteil in einer eigenen Zeile steht.
8.1. Die if Anweisung¶
Die Anweisung if wird für die bedingte Ausführung verwendet:
if_stmt ::= "if"assignment_expression":"suite("elif"assignment_expression":"suite)* ["else" ":"suite]
Es wählt genau eine der Suiten aus, indem es die Ausdrücke nacheinander auswertet, bis einer als wahr erkannt wird (siehe Abschnitt Boolesche Operationen für die Definition von „wahr“; und „falsch“.; anschließend wird diese Suite ausgeführt (und kein anderer Teil der Anweisung if wird ausgeführt oder ausgewertet). Sind alle Ausdrücke falsch, wird die Suite der Klausel else ausgeführt, sofern vorhanden.
8.2. Die Erklärung der while .¶
Die Anweisung while wird verwendet, um einen Befehl so lange wiederholt auszuführen, wie ein Ausdruck wahr ist:
while_stmt ::= "while"assignment_expression":"suite["else" ":"suite]
Dadurch wird der Ausdruck wiederholt geprüft; ist er wahr, wird die erste Suite ausgeführt; ist der Ausdruck falsch (was bereits bei der ersten Prüfung der Fall sein kann), wird die Suite der Klausel else . – sofern vorhanden – ausgeführt, und die Schleife wird beendet.
Eine in der ersten Suite ausgeführte Anweisung vom Typ break beendet die Schleife, ohne die Suite der Klausel else auszuführen. Eine in der ersten Suite ausgeführte Anweisung vom Typ continue überspringt den Rest der Suite und kehrt zur Überprüfung des Ausdrucks zurück.
8.3. Die for Anweisung¶
Die Anweisung for wird verwendet, um die Elemente einer Sequenz (wie beispielsweise einer Zeichenkette, eines Tupels oder einer Liste) oder eines anderen iterierbaren Objekts nacheinander durchzugehen:
for_stmt ::= "for"target_list"in" `!starred_list` ":"suite["else" ":"suite]
The starred_list expression is evaluated once; it should yield an
iterable object. An iterator is created for that iterable.
The first item provided
by the iterator is then assigned to the target list using the standard
rules for assignments (see Zuweisungsanweisungen), and the suite is executed. This
repeats for each item provided by the iterator. When the iterator is exhausted,
the suite in the else clause,
if present, is executed, and the loop terminates.
Eine in der ersten Suite ausgeführte Anweisung break beendet die Schleife, ohne die Suite der Klausel else auszuführen. Eine in der ersten Suite ausgeführte Anweisung continue überspringt den Rest der Suite und fährt mit dem nächsten Element fort oder, falls kein nächstes Element vorhanden ist, mit der Klausel else .
Die for-Schleife führt Zuweisungen an die Variablen in der Zielliste durch. Dadurch werden alle vorherigen Zuweisungen an diese Variablen überschrieben, einschließlich derer, die im Rahmen der for-Schleife vorgenommen wurden:
for i in range(10):
print(i)
i = 5 # Dies hat keinen Einfluss auf die for-Schleife,
# da i durch den nächsten
# Index im Bereich überschrieben wird
Die Namen in der Zielliste werden nach Beendigung der Schleife nicht gelöscht, aber wenn die Folge leer ist, wurden sie von der Schleife gar nicht erst zugewiesen. Hinweis: Der integrierte Typ range() stellt unveränderliche arithmetische Folgen von Ganzzahlen dar. Wenn man beispielsweise nacheinander range(3) durchläuft, erhält man nacheinander 0, 1 und dann 2.
Geändert in Version 3.11: Elemente mit Sternchen sind nun in der Ausdrucksliste zulässig.
8.4. Die try Anweisung¶
Die Anweisung try legt Ausnahmebehandler und/oder Aufräumcode für eine Gruppe von Anweisungen fest:
try_stmt ::=try1_stmt|try2_stmt|try3_stmttry1_stmt ::= "try" ":"suite("except" [expression["as"identifier]] ":"suite)+ ["else" ":"suite] ["finally" ":"suite] try2_stmt ::= "try" ":"suite("except" "*"expression["as"identifier] ":"suite)+ ["else" ":"suite] ["finally" ":"suite] try3_stmt ::= "try" ":"suite"finally" ":"suite
Weitere Informationen zu Ausnahmen finden Sie im Abschnitt Ausnahmen, und Informationen zur Verwendung der Anweisung raise zum Auslösen von Ausnahmen finden Sie im Abschnitt Die raise Anweisung .
8.4.1. except Klausel¶
Die Klausel(n) except legen einen oder mehrere Ausnahmebehandler fest. Tritt in der Klausel try keine Ausnahme auf, wird kein Ausnahmebehandler ausgeführt. Tritt in der Suite try eine Ausnahme auf, wird eine Suche nach einem Ausnahmebehandler gestartet. Bei dieser Suche werden die Klauseln except nacheinander durchgesehen, bis eine gefunden wird, die der Ausnahme entspricht. Eine ausdruckslose except -Klausel muss, sofern vorhanden, an letzter Stelle stehen; sie passt auf jede Ausnahme.
For an except clause with an expression, the
expression must evaluate to an exception type or a tuple of exception types.
The raised exception matches an except clause whose expression evaluates
to the class or a non-virtual base class of the exception object,
or to a tuple that contains such a class.
Wenn keine except -Klausel mit der Ausnahme übereinstimmt, wird die Suche nach einem Ausnahmehandler im umgebenden Code und auf dem Aufrufstapel fortgesetzt. [1]
Wenn bei der Auswertung eines Ausdrucks im Kopf einer except -Klausel eine Ausnahme ausgelöst wird, wird die ursprüngliche Suche nach einem Handler abgebrochen und es wird im umgebenden Code sowie auf dem Aufrufstapel nach einem Handler für die neue Ausnahme gesucht (es wird so behandelt, als hätte die gesamte :keyword:`try -Anweisung die Ausnahme ausgelöst).
Wird eine passende except -Klausel gefunden, wird die Ausnahme dem Ziel zugewiesen, das nach dem Schlüsselwort as in dieser except -Klausel angegeben ist, sofern vorhanden, und die Suite der except -Klausel wird ausgeführt. Alle except -Klauseln müssen einen ausführbaren Block enthalten. Wenn das Ende dieses Blocks erreicht ist, wird die Ausführung nach der gesamten try -Anweisung normal fortgesetzt. (Das bedeutet: Wenn zwei verschachtelte Handler für dieselbe Ausnahme existieren und die Ausnahme in der try -Klausel des inneren Handlers auftritt, wird die Ausnahme vom äußeren Handler nicht behandelt.)
Wenn eine Ausnahme mit as target zugewiesen wurde, wird sie am Ende der except -Klausel zurückgesetzt. Dies entspricht folgendem Code:
except E as N:
foo
wurde übersetzt in:
except E as N:
try:
foo
finally:
del N
Das bedeutet, dass der Ausnahme ein anderer Name zugewiesen werden muss, damit nach der except -Klausel auf sie verwiesen werden kann. Ausnahmen werden gelöscht, da sie mit dem ihnen beigefügten Traceback einen Referenzzyklus mit dem Stack-Frame bilden, wodurch alle lokalen Variablen in diesem Frame so lange erhalten bleiben, bis die nächste Garbage Collection stattfindet.
Bevor die Suite einer except -Klausel ausgeführt wird, wird die Ausnahme im Modul sys gespeichert, wo im Körper der except -Klausel durch den Aufruf von sys.exception() darauf zugegriffen werden kann. Beim Verlassen eines Ausnahmebehandlers wird die im Modul sys gespeicherte Ausnahme auf ihren vorherigen Wert zurückgesetzt:
>>> print(sys.exception())
None
>>> try:
... raise TypeError
... except:
... print(repr(sys.exception()))
... try:
... raise ValueError
... except:
... print(repr(sys.exception()))
... print(repr(sys.exception()))
...
TypeError()
ValueError()
TypeError()
>>> print(sys.exception())
None
8.4.2. except* Klausel¶
Die Klausel(n) except* legen einen oder mehrere Handler für Gruppen von Ausnahmen (Instanzen von BaseExceptionGroup) fest. Eine Anweisung try kann entweder Klauseln vom Typ except oder except* enthalten, jedoch nicht beide. Der Ausnahmetyp für den Abgleich ist im Fall von except* obligatorisch, daher ist except*: ein Syntaxfehler. Der Typ wird wie im Fall von except interpretiert, der Abgleich erfolgt jedoch anhand der Ausnahmen, die in der gerade behandelten Gruppe enthalten sind. Eine TypeError wird ausgelöst, wenn ein übereinstimmender Typ eine Unterklasse von BaseExceptionGroup ist, da dies zu einer mehrdeutigen Semantik führen würde.
Wenn im „try“-Block eine Ausnahmegruppe ausgelöst wird, teilt jede except* -Klausel (siehe split()) diese in die Untergruppen der passenden und der nicht passenden Ausnahmen auf. Ist die Untergruppe der passenden Ausnahmen nicht leer, wird sie zur behandelten Ausnahme (dem von sys.exception() zurückgegebenen Wert) und dem Ziel der except* -Klausel zugewiesen (sofern vorhanden). Anschließend wird der Hauptteil der Klausel except* ausgeführt. Ist die Untergruppe der nicht übereinstimmenden Ausnahmen nicht leer, wird sie von der nächsten Klausel except* auf dieselbe Weise verarbeitet. Dies wird so lange fortgesetzt, bis alle Ausnahmen in der Gruppe abgeglichen wurden oder die letzte Klausel except* ausgeführt wurde.
Nachdem alle except* -Klauseln ausgeführt wurden, wird die Gruppe der nicht behandelten Ausnahmen mit allen Ausnahmen zusammengeführt, die innerhalb von except* -Klauseln ausgelöst oder erneut ausgelöst wurden. Diese zusammengeführte Ausnahmegruppe wird weitergegeben an:
>>> try:
... raise ExceptionGroup("eg",
... [ValueError(1), TypeError(2), OSError(3), OSError(4)])
... except* TypeError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
... except* OSError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
...
caught <class 'ExceptionGroup'> with nested (TypeError(2),)
caught <class 'ExceptionGroup'> with nested (OSError(3), OSError(4))
+ Exception Group Traceback (most recent call last):
| File "<doctest default[0]>", line 2, in <module>
| raise ExceptionGroup("eg",
| [ValueError(1), TypeError(2), OSError(3), OSError(4)])
| ExceptionGroup: eg (1 sub-exception)
+-+---------------- 1 ----------------
| ValueError: 1
+------------------------------------
Wenn die im Block try ausgelöste Ausnahme keine Ausnahmegruppe ist und ihr Typ mit einer der Klauseln except* übereinstimmt, wird sie abgefangen und von einer Ausnahmegruppe mit einer leeren Meldungszeichenfolge umschlossen. Dadurch wird sichergestellt, dass der Typ des Ziels e durchgehend BaseExceptionGroup lautet
>>> try:
... raise BlockingIOError
... except* BlockingIOError as e:
... print(repr(e))
...
ExceptionGroup('', (BlockingIOError(),))
break, continue und return dürfen nicht in einer except* -Klausel vorkommen.
8.4.3. else Klausel¶
Die optionale Klausel else wird ausgeführt, wenn der Kontrollfluss die Suite try verlässt, keine Ausnahme ausgelöst wurde und keine Anweisung vom Typ return, continue oder break ausgeführt wurde. Ausnahmen in der Klausel else werden von den vorangehenden Klauseln except nicht behandelt.
8.4.4. finally Klausel¶
If finally is present, it specifies a ‚cleanup‘ handler. The
try clause is executed, including any except
and else clauses.
If an exception occurs in any of the clauses and is not handled,
the exception is temporarily saved.
The finally clause is executed. If there is a saved exception
it is re-raised at the end of the finally clause.
If the finally clause raises another exception, the saved exception
is set as the context of the new exception.
If the finally clause executes a return, break
or continue statement, the saved exception is discarded:
>>> def f():
... try:
... 1/0
... finally:
... return 42
...
>>> f()
42
Die Ausnahmedaten stehen dem Programm während der Ausführung der Anweisung finally nicht zur Verfügung.
Wenn eine Anweisung vom Typ return, break oder continue innerhalb der try -Suite einer Anweisung vom Typ try…finally ausgeführt wird, wird die finally -Klausel ebenfalls „beim Verlassen“ ausgeführt.
The return value of a function is determined by the last return
statement executed. Since the finally clause always executes, a
return statement executed in the finally clause will
always be the last one executed:
>>> def foo():
... try:
... return 'try'
... finally:
... return 'finally'
...
>>> foo()
'finally'
Geändert in Version 3.8: Vor Python 3.8 war eine Anweisung vom Typ continue in der Klausel finally aufgrund eines Problems bei der Implementierung unzulässig.
8.5. Die Erklärung von with .¶
Die Anweisung with dient dazu, die Ausführung eines Blocks mit Methoden zu umschließen, die von einem Kontextmanager definiert wurden (siehe Abschnitt Mit Statement-Kontextmanagern). Dadurch lassen sich gängige Verwendungsmuster wie try…except…finally zur bequemen Wiederverwendung kapseln.
with_stmt ::= "with" ( "(" with_stmt_contents ","? ")" | with_stmt_contents ) ":" suite
with_stmt_contents ::= with_item ("," with_item)*
with_item ::= expression ["as" target]
Die Ausführung der Anweisung with mit einem „Element“ verläuft wie folgt:
Der Kontextausdruck (der in der Datei
with_itemangegebene Ausdruck) wird ausgewertet, um einen Kontextmanager zu erhalten.Die
__enter__()des Kontextmanagers wird zur späteren Verwendung geladen.Die
__exit__()des Kontextmanagers wird für die spätere Verwendung geladen.Die Methode
__enter__()des Kontextmanagers wird aufgerufen.Wenn in der Anweisung
withein Ziel angegeben wurde, wird ihm der Rückgabewert von__enter__()zugewiesen.Bemerkung
Die
with-Anweisung garantiert, dass__exit__()stets aufgerufen wird, sofern die Methode__enter__()fehlerfrei zurückkehrt. Tritt also während der Zuweisung an die Ziel-Liste ein Fehler auf, so wird dieser genauso behandelt wie ein Fehler innerhalb des Anweisungsblocks. Siehe Schritt 7 weiter unten.Die Suite wurde aufgeführt.
Die Methode
__exit__()des Kontextmanagers wird aufgerufen. Wenn eine Ausnahme zum Abbruch der Suite geführt hat, werden deren Typ, Wert und Traceback als Argumente an__exit__()übergeben. Andernfalls werden drei Argumente vom TypNoneübergeben.Wurde die Suite aufgrund einer Ausnahme beendet und war der Rückgabewert der Methode
__exit__()false, wird die Ausnahme erneut ausgelöst. War der Rückgabewert true, wird die Ausnahme unterdrückt, und die Ausführung wird mit der Anweisung fortgesetzt, die auf die Anweisungwithfolgt.Wurde die Suite aus einem anderen Grund als einer Ausnahme beendet, wird der Rückgabewert von
__exit__()ignoriert, und die Ausführung wird an der für die jeweilige Beendigungsart üblichen Stelle fortgesetzt.
Der folgende Code:
with EXPRESSION as TARGET:
SUITE
ist semantisch gleichbedeutend mit:
manager = (EXPRESSION)
enter = manager.__enter__
exit = manager.__exit__
value = enter()
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not exit(*sys.exc_info()):
raise
finally:
if not hit_except:
exit(None, None, None)
mit der Ausnahme, dass für __enter__() und __exit__() die implizite Spezialmethoden-Suche verwendet wird.
Bei mehr als einem Element werden die Kontextmanager so verarbeitet, als wären mehrere with -Anweisungen verschachtelt:
with A() as a, B() as b:
SUITE
ist semantisch gleichbedeutend mit:
with A() as a:
with B() as b:
SUITE
Sie können Kontextmanager mit mehreren Elementen auch über mehrere Zeilen hinweg schreiben, wenn die Elemente in Klammern stehen. Zum Beispiel:
with (
A() as a,
B() as b,
):
SUITE
Geändert in Version 3.1: Unterstützung für mehrere Kontext-Ausdrücke.
Geändert in Version 3.10: Unterstützung für die Verwendung von Gruppierungsklammern, um die Anweisung auf mehrere Zeilen aufzuteilen.
8.6. Die Erklärung der match Anweisung¶
Added in version 3.10.
Die „match“-Anweisung dient zum Musterabgleich. Syntax:
match_stmt ::= 'match'subject_expr":" NEWLINE INDENTcase_block+ DEDENT subject_expr ::=flexible_expression"," [flexible_expression_list[',']] |assignment_expressioncase_block ::= 'case'patterns[guard] ":"suite
Bemerkung
In diesem Abschnitt werden einfache Anführungszeichen verwendet, um Soft-Schlüsselwörter zu kennzeichnen.
Beim Musterabgleich werden ein Muster als Eingabe (gemäß case) und ein Zielwert (gemäß match) verwendet. Das Muster (das Untermuster enthalten kann) wird mit dem Zielwert abgeglichen. Die möglichen Ergebnisse sind:
Ein Übereinstimmungserfolg oder -misserfolg (auch als Mustererfolg oder -misserfolg bezeichnet).
Mögliche Zuordnung übereinstimmender Werte zu einem Namen. Die Voraussetzungen hierfür werden im Folgenden näher erläutert.
Die Schlüsselwörter match und case sind Soft-Schlüsselwörter.
Siehe auch
8.6.1. Übersicht¶
Hier ist ein Überblick über den logischen Ablauf einer „match“-Anweisung:
Der Subjekt-Ausdruck
subject_exprwird ausgewertet und der resultierende Subjektwert ermittelt. Enthält der Subjekt-Ausdruck ein Komma, wird ein Tupel gemäß den Standardregeln gebildet.Jedes Muster in einem
case_blockwird mit dem entsprechenden Wert abgeglichen. Die konkreten Regeln für Erfolg oder Misserfolg werden im Folgenden beschrieben. Der Abgleichversuch kann auch einige oder alle eigenständigen Namen innerhalb des Musters binden. Die genauen Regeln für die Musterbindung variieren je nach Mustertyp und werden im Folgenden näher erläutert. Namensbindungen, die während eines erfolgreichen Musterabgleichs vorgenommen werden, bestehen über den ausgeführten Block hinaus fort und können nach der `match`-Anweisung verwendet werden.Bemerkung
Bei fehlgeschlagenen Musterabgleichen können einige Teilmuster erfolgreich sein. Verlassen Sie sich nicht darauf, dass bei einem fehlgeschlagenen Abgleich Bindungen hergestellt werden. Verlassen Sie sich umgekehrt auch nicht darauf, dass Variablen nach einem fehlgeschlagenen Abgleich unverändert bleiben. Das genaue Verhalten hängt von der Implementierung ab und kann variieren. Dies ist eine bewusste Entscheidung, die getroffen wurde, um verschiedenen Implementierungen die Möglichkeit zu geben, Optimierungen hinzuzufügen.
Wenn das Muster erfolgreich ist, wird die entsprechende Bedingung (sofern vorhanden) ausgewertet. In diesem Fall ist gewährleistet, dass alle Namenszuordnungen bereits erfolgt sind.
Wenn die Bedingung wahr ist oder fehlt, wird die Anweisung
blockinnerhalb voncase_blockausgeführt.Andernfalls wird, wie oben beschrieben, der nächste
case_blockversucht.Wenn keine weiteren Fallblöcke mehr vorhanden sind, ist die „match“-Anweisung abgeschlossen.
Bemerkung
Benutzer sollten sich grundsätzlich nie darauf verlassen, dass ein Muster ausgewertet wird. Je nach Implementierung speichert der Interpreter Werte möglicherweise im Cache oder nutzt andere Optimierungen, durch die wiederholte Auswertungen übersprungen werden.
Ein Beispiel für eine Abgleichsanweisung:
>>> flag = False
>>> match (100, 200):
... case (100, 300): # Keine Übereinstimmung: 200 ≠ 300
... print('Fall 1')
... case (100, 200) if flag: # Übereinstimmung erfolgreich, aber Bedingung nicht erfüllt
... print('Fall 2')
... case (100, y): # Übereinstimmung und y wird auf 200 gesetzt
... print(f'Fall 3, y: {y}')
... case _: # Muster wird nicht versucht
... print('Fall 4, ich passe auf alles!')
...
Fall 3, y: 200
In diesem Fall ist if flag ein Guard. Mehr dazu erfahren Sie im nächsten Abschnitt.
8.6.2. Guards¶
guard ::= "if" assignment_expression
Ein guard (der Teil des case ist) muss erfolgreich sein, damit der Code innerhalb des case -Blocks ausgeführt wird. Er hat folgende Form: if, gefolgt von einem Ausdruck.
Der logische Ablauf eines case -Blocks mit einem guard sieht wie folgt aus:
Überprüfen Sie, ob die Musterprüfung im Block
caseerfolgreich war. Falls die Musterprüfung fehlgeschlagen ist, wird der Blockguardnicht ausgewertet und der nächste Blockcasegeprüft.Wenn die Mustererkennung erfolgreich war, werte die
guardaus.Wenn die Bedingung
guardals wahr ausgewertet wird, wird der „case“-Block ausgewählt.Wenn die Bedingung
guardals „falsch“ ausgewertet wird, wird der „case“-Block nicht ausgewählt.Wenn die
guardwährend der Auswertung eine Ausnahme auslöst, wird diese nach oben weitergeleitet.
Guards dürfen Nebenwirkungen haben, da es sich um Ausdrücke handelt. Die Auswertung der Guards muss vom ersten bis zum letzten Case-Block nacheinander erfolgen, wobei Case-Blöcke übersprungen werden, deren Muster nicht alle erfolgreich sind. (Das heißt, die Auswertung der Guards muss in der richtigen Reihenfolge erfolgen.) Die Auswertung der Guards muss beendet werden, sobald ein Case-Block ausgewählt wurde.
8.6.3. Unwiderlegbare Argumente¶
Ein unwiderlegbarer Fallblock ist ein Fallblock, der alle Fälle abdeckt. Eine match-Anweisung darf höchstens einen unwiderlegbaren Fallblock enthalten, und dieser muss an letzter Stelle stehen.
Ein Fallblock gilt als unwiderlegbar, wenn er keine Schutzklausel enthält und sein Muster unwiderlegbar ist. Ein Muster gilt als unwiderlegbar, wenn sich allein anhand seiner Syntax nachweisen lässt, dass es immer erfolgreich ist. Nur die folgenden Muster sind unwiderlegbar:
AS-Muster dessen linke Seite unwiderlegbar ist
ODER („Oder“) Muster das mindestens ein unwiderlegbares Muster enthält
in Klammern gesetzte, unwiderlegbare Muster
8.6.4. Muster¶
Bemerkung
In diesem Abschnitt werden Grammatiknotationen verwendet, die über die Standard-EBNF hinausgehen:
Die Schreibweise
SEP.RULE+ist eine Kurzschreibweise fürRULE (SEP RULE)*Die Schreibweise
!RULEist eine Kurzform für eine negative Lookahead-Bedingung.
Die übergeordnete Syntax für patterns lautet:
patterns ::=open_sequence_pattern|patternpattern ::=as_pattern|or_patternclosed_pattern ::= |literal_pattern|capture_pattern|wildcard_pattern|value_pattern|group_pattern|sequence_pattern|mapping_pattern|class_pattern
Die folgenden Beschreibungen enthalten zur Veranschaulichung eine „einfach formulierte“; Erläuterung der Funktionsweise eines Musters (Dank gilt Raymond Hettinger für ein Dokument, das als Vorlage für die meisten dieser Beschreibungen diente). Bitte beachten Sie, dass diese Beschreibungen rein zur Veranschaulichung dienen und möglicherweise nicht die zugrunde liegende Implementierung widerspiegeln. Außerdem decken sie nicht alle gültigen Formen ab.
8.6.4.1. ODER („Oder“) Muster¶
Ein OR-Muster besteht aus zwei oder mehr Mustern, die durch senkrechte Striche getrennt sind: |. Syntax:
or_pattern ::= "|".closed_pattern+
Nur das letzte Teilmuster darf irrefutable sein, und jedes Teilmuster muss dieselbe Menge von Namen binden, um Mehrdeutigkeiten zu vermeiden.
Ein OR-Muster gleicht nacheinander jedes seiner Teilmuster mit dem Suchwert ab, bis eines davon übereinstimmt. Das OR-Muster gilt dann als erfolgreich. Andernfalls, wenn keines der Teilmuster übereinstimmt, schlägt das OR-Muster fehl.
Einfach ausgedrückt: P1 | P2 | ... versucht zunächst, P1 abzugleichen; sollte dies fehlschlagen, wird P2 versucht. Sobald einer der Versuche erfolgreich ist, ist der Vorgang abgeschlossen; andernfalls schlägt er fehl.
8.6.4.2. AS-Muster¶
Ein „AS“-Muster gleicht ein „OR“-Muster links vom Schlüsselwort as mit einem Subjekt ab. Syntax:
as_pattern ::=or_pattern"as"capture_pattern
Wenn das OR-Muster fehlschlägt, schlägt auch das AS-Muster fehl. Andernfalls bindet das AS-Muster das Subjekt an den Namen rechts vom Schlüsselwort „as“. und ist erfolgreich. capture_pattern darf kein _ sein.
Einfach ausgedrückt: P as NAME wird mit P abgeglichen, und bei Erfolg wird NAME = <subject> gesetzt.
8.6.4.3. Literale Muster¶
Ein Literalmuster entspricht den meisten Literalen in Python. Syntax:
literal_pattern ::=signed_number|signed_number"+" NUMBER |signed_number"-" NUMBER | `!strings` | "None" | "True" | "False" signed_number ::= ["-"] NUMBER
The rule strings and the token NUMBER are defined in the
standard Python grammar. Triple-quoted strings are
supported. Raw strings and byte strings are supported. f-Strings are
not supported.
Die Formate signed_number '+' NUMBER und signed_number '-' NUMBER dienen zur Darstellung von komplexen Zahlen; sie erfordern links eine reelle Zahl und rechts eine imaginäre Zahl. Beispiel: 3 + 4j.
Einfach ausgedrückt: LITERAL ist nur dann erfolgreich, wenn <subject> == LITERAL . Für die einmaligen Objekte (Singleton) None, True und False wird der Operator is verwendet.
8.6.4.4. Erfassungsmuster / Capture-Muster¶
Ein Capture-Muster ordnet den Wert des Subjekts einem Namen zu. Syntax:
capture_pattern ::= !'_' NAME
Ein einzelner Unterstrich _ ist kein Capture-Muster (dies wird durch !'_' ausgedrückt). Er wird stattdessen als wildcard_pattern behandelt.
In einem bestimmten Muster kann ein bestimmter Name nur einmal verwendet werden. Beispielsweise ist case x, x: ... ungültig, während case [x] | x: ... zulässig ist.
Capture-Muster sind immer erfolgreich. Die Bindung folgt den Regeln für den Gültigkeitsbereich, die durch den Zuweisungsausdrucksoperator in PEP 572 festgelegt sind; der Name wird zu einer lokalen Variablen im nächstgelegenen übergeordneten Funktionsgültigkeitsbereich, sofern keine entsprechende Anweisung vom Typ global oder nonlocal vorliegt.
Einfach ausgedrückt: NAME wird immer erfolgreich sein und NAME = <subject> setzen.
8.6.4.5. Platzhaltermuster¶
Ein Platzhaltermuster ist immer erfolgreich (passt auf alles) und bindet keinen Namen. Syntax:
wildcard_pattern ::= '_'
_ ist ein Soft-Schlüsselwort innerhalb beliebiger Muster, jedoch ausschließlich innerhalb von Mustern. Es handelt sich wie üblich um einen Bezeichner, selbst innerhalb von match Subjekt-Ausdrücken, guards und case Blöcken.
Einfach ausgedrückt: _ wird immer erfolgreich sein.
8.6.4.6. Wertmuster¶
Ein Wertmuster repräsentiert einen benannten Wert in Python. Syntax:
value_pattern ::=attrattr ::=name_or_attr"." NAME name_or_attr ::=attr| NAME
Der mit einem Punkt gekennzeichnete Name im Muster wird anhand der Standardregeln für die Namensauflösung in Python nachgeschlagen: :ref:` <resolve_names>`. Das Muster ist erfolgreich, wenn der gefundene Wert mit dem Suchwert übereinstimmt (unter Verwendung des Gleichheitsoperators == ).
Einfach ausgedrückt: NAME1.NAME2 wird nur dann erfolgreich sein, wenn <subject> == NAME1.NAME2
Bemerkung
Wenn derselbe Wert mehrmals in derselben „match“-Anweisung vorkommt, kann der Interpreter den zuerst gefundenen Wert zwischenspeichern und wiederverwenden, anstatt die Suche erneut durchzuführen. Dieser Zwischenspeicher ist streng an eine bestimmte Ausführung einer bestimmten „match“-Anweisung gebunden.
8.6.4.7. Gruppenmuster¶
Ein Gruppenmuster ermöglicht es Benutzern, Muster in Klammern zu setzen, um die beabsichtigte Gruppierung hervorzuheben. Ansonsten gibt es keine zusätzliche Syntax. Syntax:
group_pattern ::= "(" pattern ")"
Einfach ausgedrückt hat (P) dieselbe Wirkung wie P .
8.6.4.8. Sequenzmuster¶
Ein Sequenzmuster enthält mehrere Untermuster, die mit Sequenzelementen abgeglichen werden sollen. Die Syntax ähnelt dem Entpacken einer Liste oder eines Tupels.
sequence_pattern ::= "[" [maybe_sequence_pattern] "]" | "(" [open_sequence_pattern] ")" open_sequence_pattern ::=maybe_star_pattern"," [maybe_sequence_pattern] maybe_sequence_pattern ::= ",".maybe_star_pattern+ ","? maybe_star_pattern ::=star_pattern|patternstar_pattern ::= "*" (capture_pattern|wildcard_pattern)
Es spielt keine Rolle, ob für Sequenzmuster runde Klammern oder eckige Klammern verwendet werden (d. h. (...) vs. [...] ).
Bemerkung
Ein einzelnes Muster in runden Klammern ohne abschließendes Komma (z. B. (3 | 4)) ist ein Gruppenmuster. Ein einzelnes Muster in eckigen Klammern (z. B. [3 | 4]) ist hingegen weiterhin ein Sequenzmuster.
Ein Sequenzmuster darf höchstens ein Stern-Teilmuster enthalten. Das Stern-Teilmuster kann an beliebiger Stelle vorkommen. Ist kein Stern-Teilmuster vorhanden, handelt es sich um ein Sequenzmuster fester Länge; andernfalls handelt es sich um ein Sequenzmuster variabler Länge.
Im Folgenden wird der logische Ablauf beim Abgleich eines Sequenzmusters mit einem Zielwert beschrieben:
Ist der Wert des Subjekts keine Sequenz [2], schlägt das Sequenzmuster fehl.
Wenn der Wert des Subjekts eine Instanz von
str,bytesoderbytearrayist, schlägt das Sequenzmuster fehl.Die weiteren Schritte hängen davon ab, ob das Sequenzmuster eine feste oder eine variable Länge hat.
Wenn das Sequenzmuster eine feste Länge hat:
Wenn die Länge der zu prüfenden Sequenz nicht mit der Anzahl der Teilmuster übereinstimmt, schlägt die Sequenzprüfung fehl.
Teilmuster im Sequenzmuster werden von links nach rechts mit den entsprechenden Elementen in der zu prüfenden Sequenz abgeglichen. Der Abgleich wird beendet, sobald ein Teilmuster nicht übereinstimmt. Wenn alle Teilmuster erfolgreich mit den entsprechenden Elementen abgeglichen werden, gilt das Sequenzmuster als erfolgreich.
Andernfalls, wenn das Sequenzmuster eine variable Länge hat:
Ist die Länge der zu prüfenden Sequenz kürzer als die Anzahl der Nicht-Stern-Teilmuster, gilt das Sequenzmuster als nicht erfüllt.
Die führenden Teilmuster ohne Sternzeichen werden wie bei Sequenzen fester Länge ihren entsprechenden Elementen zugeordnet.
Wenn der vorherige Schritt erfolgreich ist, passt das Stern-Teilmuster auf eine Liste, die aus den verbleibenden Suchbegriffen gebildet wird, wobei die verbleibenden Begriffe, die Nicht-Stern-Teilmuster im Anschluss an das Stern-Teilmuster entsprechen, ausgeschlossen werden.
Die verbleibenden Teilmuster ohne Stern werden wie bei einer Sequenz fester Länge ihren entsprechenden Subjektelementen zugeordnet.
Bemerkung
Die Länge der Objektsequenz wird über
len()ermittelt (d. h. über das__len__()Protokoll ). Diese Länge kann vom Interpreter auf ähnliche Weise wie Wertmuster zwischengespeichert werden.
Einfach ausgedrückt: [P1, P2, P3,… , P<N>] ergibt nur dann eine Übereinstimmung, wenn alle folgenden Bedingungen erfüllt sind:
Überprüfe, ob
<subject>eine Folge istlen(subject) == <N>P1entspricht<subject>[0](beachte, dass diese Übereinstimmung auch Namen binden kann)P2entspricht<subject>[1](beachte, dass diese Übereinstimmung auch Namen binden kann)… und so weiter für das jeweilige Muster bzw. Element.
8.6.4.9. Zuordnungsmuster¶
Ein Zuordnungsmuster enthält ein oder mehrere Schlüssel-Wert-Muster. Die Syntax ähnelt dem Aufbau eines Wörterbuchs. Syntax:
mapping_pattern ::= "{" [items_pattern] "}"
items_pattern ::= ",".key_value_pattern+ ","?
key_value_pattern ::= (literal_pattern | value_pattern) ":" pattern
| double_star_pattern
double_star_pattern ::= "**" capture_pattern
Ein Zuordnungsmuster darf höchstens ein Doppelsternmuster enthalten. Das Doppelsternmuster muss das letzte Teilmuster im Zuordnungsmuster sein.
Doppelte Schlüssel in Zuordnungsmustern sind nicht zulässig. Doppelte Literalschlüssel lösen eine SyntaxError aus. Zwei Schlüssel, die ansonsten denselben Wert haben, lösen zur Laufzeit eine ValueError aus.
Im Folgenden wird der logische Ablauf beim Abgleich eines Zuordnungsmusters mit einem Objektwert beschrieben:
Wenn der Wert des Subjekts kein Zuordnungs [3] ist, schlägt das Zuordnungsmuster fehl.
Wenn jeder im Zuordnungsmuster angegebene Schlüssel in der Zielzuordnung vorhanden ist und das Muster für jeden Schlüssel mit dem entsprechenden Eintrag in der Zielzuordnung übereinstimmt, ist das Zuordnungsmuster erfolgreich.
Werden im Zuordnungsmuster doppelte Schlüssel erkannt, gilt das Muster als ungültig. Bei doppelten Literalwerten wird eine
SyntaxErrorausgelöst; bei benannten Schlüsseln mit identischem Wert eineValueError.
Bemerkung
Schlüssel-Wert-Paare werden mithilfe der Zwei-Argument-Form der Methode get() des Mapping-Objekts abgeglichen. Die abgeglichenen Schlüssel-Wert-Paare müssen bereits im Mapping vorhanden sein und dürfen nicht dynamisch über __missing__() oder __getitem__() erstellt werden.
Einfach ausgedrückt: {KEY1: P1, KEY2: P2, ... } ergibt nur dann eine Übereinstimmung, wenn alle folgenden Bedingungen erfüllt sind:
Schau mal unter
<subject>nach – dort findest du eine Karte.KEY1 in <subject>P1stimmt mit<subject>[KEY1]überein.… und so weiter für das jeweilige Schlüssel-Muster-Paar.
8.6.4.10. Klassenmuster¶
Ein Klassenmuster repräsentiert eine Klasse sowie deren Positions- und Schlüsselwortargumente (sofern vorhanden). Syntax:
class_pattern ::=name_or_attr"(" [pattern_arguments","?] ")" pattern_arguments ::=positional_patterns[","keyword_patterns] |keyword_patternspositional_patterns ::= ",".pattern+ keyword_patterns ::= ",".keyword_pattern+ keyword_pattern ::= NAME "="pattern
Dasselbe Schlüsselwort sollte in Klassenmustern nicht wiederholt werden.
Im Folgenden wird der logische Ablauf beim Abgleich eines Klassenmusters mit einem Subjektwert beschrieben:
Wenn
name_or_attrkeine Instanz der integrierten Klassetypeist, wird einTypeErrorausgelöst.Wenn der Wert des Subjekts keine Instanz von
name_or_attrist (geprüft überisinstance()) , schlägt das Klassenmuster fehl.Sind keine Musterargumente vorhanden, ist die Musterprüfung erfolgreich. Andernfalls hängen die nachfolgenden Schritte davon ab, ob Muster für Schlüsselwort- oder Positionsargumente vorhanden sind.
Bei einer Reihe von integrierten Typen (siehe unten) wird ein einzelnes positionelles Teilmuster akzeptiert, das mit dem gesamten Subjekt übereinstimmt; bei diesen Typen funktionieren Schlüsselwortmuster ebenso wie bei anderen Typen.
Sind nur Schlüsselwortmuster vorhanden, werden diese nacheinander wie folgt verarbeitet:
Das Schlüsselwort wird als Attribut des Subjekts nachgeschlagen.
Wenn dabei eine andere Ausnahme als
AttributeErrorausgelöst wird, wird die Ausnahme weitergeleitet.Wenn dabei ein
AttributeErrorausgelöst wird, ist das Klassenmuster fehlgeschlagen.Andernfalls wird das mit dem Schlüsselwortmuster verknüpfte Teilmuster mit dem Attributwert des Subjekts abgeglichen. Gelingt dies nicht, schlägt das Klassenmuster fehl; gelingt es, wird der Abgleich mit dem nächsten Schlüsselwort fortgesetzt.
Wenn alle Schlüsselwortmuster erfolgreich sind, ist das Klassenmuster erfolgreich.
Falls Positionsmuster vorhanden sind, werden diese vor dem Abgleich mithilfe des Attributs
__match_args__der Klassename_or_attrin Schlüsselwortmuster umgewandelt:Es wird das Äquivalent von
getattr(cls, "__match_args__", ())aufgerufen.Wenn dabei eine Ausnahme ausgelöst wird, wird diese nach oben weitergeleitet.
Wenn der Rückgabewert kein Tupel ist, schlägt die Konvertierung fehl und es wird ein
TypeError-Fehler ausgelöst.Wenn es mehr Positionsmuster gibt als
len(cls.__match_args__), wirdTypeErrorausgelöst.Andernfalls wird das Positionsmuster
imithilfe von__match_args__[i]als Schlüsselwort in ein Schlüsselwortmuster umgewandelt.__match_args__[i]muss eine Zeichenkette sein; andernfalls wirdTypeErrorausgelöst.Wenn doppelte Schlüsselwörter vorhanden sind, wird ein
TypeErrorausgelöst.
Sobald alle Positionsmuster in Schlüsselwortmuster umgewandelt wurden, verläuft die Suche so, als gäbe es nur Schlüsselwortmuster.
Bei den folgenden integrierten Typen unterscheidet sich die Behandlung von Positionsuntermustern:
Diese Klassen akzeptieren ein einzelnes positionsbezogenes Argument, und das Muster wird dabei mit dem gesamten Objekt abgeglichen und nicht mit einem Attribut. Beispielsweise passt
int(0|1)auf den Wert0, nicht jedoch auf den Wert0.0.
Einfach ausgedrückt passt CLS(P1, attr=P2) nur dann, wenn Folgendes zutrifft:
isinstance(<subject>, CLS)P1mithilfe vonCLS.__match_args__in ein Schlüsselwortmuster umwandelnFür jedes Schlüsselwortargument
attr=P2:hasattr(<subject>, "attr")P2stimmt mit<subject>.attrüberein
… und so weiter für das entsprechende Schlüsselwort-Argument-Muster-Paar.
8.7. Funktionsdefinitionen¶
Eine Funktionsdefinition definiert ein benutzerdefiniertes Funktionsobjekt (siehe Abschnitt Die Standardtyp-Hierarchie):
funcdef ::= [decorators] "def"funcname[type_params] "(" [parameter_list] ")" ["->"expression] ":"suitedecorators ::=decorator+ decorator ::= "@"assignment_expressionNEWLINE parameter_list ::=defparameter(","defparameter)* "," "/" ["," [parameter_list_no_posonly]] |parameter_list_no_posonlyparameter_list_no_posonly ::=defparameter(","defparameter)* ["," [parameter_list_starargs]] |parameter_list_starargsparameter_list_starargs ::= "*"star_parameter(","defparameter)* ["," [parameter_star_kwargs]] | "*" (","defparameter)+ ["," [parameter_star_kwargs]] |parameter_star_kwargsparameter_star_kwargs ::= "**"parameter[","] parameter ::=identifier[":"expression] star_parameter ::=identifier[":" ["*"]expression] defparameter ::=parameter["="expression] funcname ::=identifier
Eine Funktionsdefinition ist eine ausführbare Anweisung. Durch ihre Ausführung wird der Funktionsname im aktuellen lokalen Namensraum an ein Funktionsobjekt gebunden (eine Hülle um den ausführbaren Code der Funktion). Dieses Funktionsobjekt enthält einen Verweis auf den aktuellen globalen Namensraum als den globalen Namensraum, der beim Aufruf der Funktion verwendet werden soll.
Bei der Funktionsdefinition wird der Funktionskörper nicht ausgeführt; dieser wird erst ausgeführt, wenn die Funktion aufgerufen wird. [4]
Eine Funktionsdefinition kann von einem oder mehreren Decorator-Ausdrücken umschlossen sein. Decorator-Ausdrücke werden bei der Definition der Funktion in dem Geltungsbereich ausgewertet, der die Funktionsdefinition enthält. Das Ergebnis muss ein aufrufbares Objekt sein, das mit dem Funktionsobjekt als einzigem Argument aufgerufen wird. Der zurückgegebene Wert wird an den Funktionsnamen statt an das Funktionsobjekt gebunden. Mehrere Dekoratoren werden verschachtelt angewendet. Beispielsweise der folgende Code
@f1(arg)
@f2
def func(): pass
entspricht in etwa
def func(): pass
func = f1(arg)(f2(func))
außer dass die ursprüngliche Funktion nicht vorübergehend an den Namen func gebunden ist.
Geändert in Version 3.9: Funktionen können mit jedem gültigen assignment_expression versehen werden. Früher war die Syntax wesentlich restriktiver; weitere Informationen finden Sie unter PEP 614.
Eine Liste von Typ-Parametern kann in eckigen Klammern zwischen dem Namen der Funktion und der öffnenden Klammer für ihre Parameterliste angegeben werden. Dies signalisiert statischen Typprüfern, dass es sich um eine generische Funktion handelt. Zur Laufzeit können die Typ-Parameter über das Attribut __type_params__ der Funktion abgerufen werden. Weitere Informationen finden Sie unter Generische Funktionen.
Geändert in Version 3.12: Typ-Parameterlisten sind eine Neuerung in Python 3.12.
Wenn ein oder mehrere Parameter die Form Parameter = Ausdruck haben, spricht man davon, dass die Funktion „Standardparameterwerte“; besitzt. Bei einem Parameter mit einem Standardwert kann das entsprechende Argument bei einem Aufruf weggelassen werden; in diesem Fall wird der Standardwert des Parameters eingesetzt. Wenn ein Parameter einen Standardwert hat, müssen auch alle nachfolgenden Parameter bis zum * einen Standardwert haben – dies ist eine syntaktische Einschränkung, die in der Grammatik nicht ausdrücklich erwähnt wird.
Standardparameterwerte werden bei der Ausführung der Funktionsdefinition von links nach rechts ausgewertet. Das bedeutet, dass der Ausdruck einmalig bei der Definition der Funktion ausgewertet wird und dass bei jedem Aufruf derselbe „vorberechnete“ Wert verwendet wird. Dies ist besonders wichtig zu verstehen, wenn ein Standardparameterwert ein veränderliches Objekt ist, wie beispielsweise eine Liste oder ein Wörterbuch: Wenn die Funktion das Objekt verändert (z. B. durch Anhängen eines Elements an eine Liste), wird der Standardparameterwert faktisch verändert. Dies ist in der Regel nicht beabsichtigt. Eine Möglichkeit, dies zu umgehen, besteht darin, None als Standardwert zu verwenden und im Funktionskörper explizit darauf zu prüfen, zum Beispiel:
def was_läuft_im_Fernseher(Pinguin=None):
if Pinguin is None:
Pinguin = []
Pinguin.append("Eigentum des Zoos")
return Pinguin
Die Semantik von Funktionsaufrufen wird im Abschnitt Calls näher beschrieben. Ein Funktionsaufruf weist allen in der Parameterliste genannten Parametern Werte zu, entweder aus Positionsargumenten, aus Schlüsselwortargumenten oder aus Standardwerten. Ist die Form *identifier vorhanden, wird sie mit einem Tupel initialisiert, das alle überschüssigen Positionsargumente aufnimmt; der Standardwert ist ein leeres Tupel. Ist die Form **identifier vorhanden, wird sie mit einer neuen geordneten Zuordnung initialisiert, die alle überschüssigen Schlüsselwortargumente aufnimmt; der Standardwert ist eine neue leere Zuordnung desselben Typs. Parameter nach * oder *identifier sind reine Schlüsselwortparameter und dürfen nur über Schlüsselwortargumente übergeben werden. Parameter vor / sind reine Positionsparameter und dürfen nur über Positionsargumente übergeben werden.
Geändert in Version 3.8: Die Parametersyntax der Funktion / kann verwendet werden, um rein positionelle Parameter anzugeben. Weitere Informationen finden Sie unter PEP 570.
Parameters may have an annotation of the form „: expression“
following the parameter name. Any parameter may have an annotation, even those of the form
*identifier or **identifier. (As a special case, parameters of the form
*identifier may have an annotation „: *expression“.) Functions may have „return“ annotation of
the form „-> expression“ after the parameter list. These annotations can be
any valid Python expression. The presence of annotations does not change the
semantics of a function. The annotation values are available as values of
a dictionary keyed by the parameters‘ names in the __annotations__
attribute of the function object. If the annotations import from
__future__ is used, annotations are preserved as strings at runtime which
enables postponed evaluation. Otherwise, they are evaluated when the function
definition is executed. In this case annotations may be evaluated in
a different order than they appear in the source code.
Geändert in Version 3.11: Parameter der Form *identifier können mit der Anmerkung : *expression versehen sein. Siehe PEP 646.
Es ist auch möglich, anonyme Funktionen (Funktionen, die nicht an einen Namen gebunden sind) zu erstellen, die direkt in Ausdrücken verwendet werden können. Hierfür werden Lambda-Ausdrücke verwendet, die im Abschnitt Lambdas beschrieben sind. Beachten Sie, dass der Lambda-Ausdruck lediglich eine Kurzschreibweise für eine vereinfachte Funktionsdefinition ist; eine in einer def -Anweisung definierte Funktion kann genau wie eine durch einen Lambda-Ausdruck definierte Funktion weitergegeben oder einem anderen Namen zugewiesen werden. Die Form def ist sogar noch leistungsfähiger, da sie die Ausführung mehrerer Anweisungen und Annotationen ermöglicht.
Anmerkung des Programmierers: Funktionen sind Objekte erster Klasse. Eine innerhalb einer Funktionsdefinition ausgeführte Anweisung def definiert eine lokale Funktion, die zurückgegeben oder weitergegeben werden kann. Freie Variablen, die in der verschachtelten Funktion verwendet werden, können auf die lokalen Variablen der Funktion zugreifen, die die „def“-Anweisung enthält. Weitere Informationen finden Sie im Abschnitt Benennung und Zuordnung .
Siehe auch
- PEP 3107 - Funktionsanmerkungen
Die ursprüngliche Spezifikation für Funktionsannotationen.
- PEP 484 - Typ-Hinweise
Definition einer einheitlichen Bedeutung für Anmerkungen: Typhinweise.
- PEP 526 - Syntax für Variablenanmerkungen
Möglichkeit, Typangaben für Variablendeklarationen zu machen, einschließlich Klassenvariablen und Instanzvariablen.
- PEP 563 - Aufgeschobene Auswertung von Anmerkungen
Unterstützung für Vorwärtsverweise innerhalb von Anmerkungen durch die Beibehaltung der Anmerkungen in Zeichenfolgenform zur Laufzeit anstelle einer sofortigen Auswertung.
- PEP 318 - Dekoratoren für Funktionen und Methoden
Es wurden Funktions- und Methoden-Dekoratoren eingeführt. Klassendekoratoren wurden in PEP 3129 eingeführt.
8.8. Klassendefinitionen¶
Eine Klassendefinition definiert ein Klassenobjekt (siehe Abschnitt Die Standardtyp-Hierarchie):
classdef ::= [decorators] "class"classname[type_params] [inheritance] ":"suiteinheritance ::= "(" [argument_list] ")" classname ::=identifier
Eine Klassendefinition ist eine ausführbare Anweisung. Die Vererbungsliste enthält in der Regel eine Auflistung von Basisklassen (siehe Metaklassen für fortgeschrittenere Anwendungsmöglichkeiten), daher sollte jedes Element der Liste zu einem Klassenobjekt ausgewertet werden, das die Erstellung von Unterklassen zulässt. Klassen ohne Vererbungsliste erben standardmäßig von der Basisklasse object ; daher gilt:
class Foo:
pass
entspricht
class Foo(object):
pass
Die Suite der Klasse wird dann in einem neuen Ausführungsrahmen (siehe Benennung und Zuordnung) unter Verwendung eines neu erstellten lokalen Namensraums und des ursprünglichen globalen Namensraums ausgeführt. (In der Regel enthält die Suite hauptsächlich Funktionsdefinitionen.) Wenn die Suite der Klasse die Ausführung beendet hat, wird ihr Ausführungsrahmen verworfen, ihr lokaler Namensraum jedoch gespeichert. [5] Anschließend wird ein Klassenobjekt unter Verwendung der Vererbungsliste für die Basisklassen und des gespeicherten lokalen Namensraums für das Attributwörterbuch erstellt. Der Klassenname wird im ursprünglichen lokalen Namensraum an dieses Klassenobjekt gebunden.
Die Reihenfolge, in der die Attribute im Klassenkörper definiert sind, bleibt im __dict__ der neuen Klasse erhalten. Beachten Sie, dass dies nur unmittelbar nach der Erstellung der Klasse und nur für Klassen gilt, die mithilfe der Definitionssyntax definiert wurden.
Die Erstellung von Klassen lässt sich mithilfe von Metaklassen umfassend anpassen.
Auch Klassen können dekoriert werden: genau wie beim Dekorieren von Funktionen,
@f1(arg)
@f2
class Foo: pass
entspricht in etwa
class Foo: pass
Foo = f1(arg)(f2(Foo))
Die Auswertungsregeln für Dekoratorausdrücke entsprechen denen für Funktionsdekoratoren. Das Ergebnis wird dann an den Klassennamen gebunden.
Geändert in Version 3.9: Klassen können mit beliebigen gültigen assignment_expression dekoriert werden. Früher war die Syntax wesentlich restriktiver; Einzelheiten finden Sie unter PEP 614.
Eine Liste der Typ-Parameter kann unmittelbar nach dem Namen der Klasse in eckigen Klammern angegeben werden. Dies signalisiert statischen Typprüfern, dass es sich um eine generische Klasse handelt. Zur Laufzeit können die Typ-Parameter über das Attribut __type_params__ der Klasse abgerufen werden. Weitere Informationen finden Sie unter Generische Klassen.
Geändert in Version 3.12: Typ-Parameterlisten sind eine Neuerung in Python 3.12.
Anmerkung für Programmierer: In der Klassendefinition definierte Variablen sind Klassenattribute; sie werden von allen Instanzen gemeinsam genutzt. Instanzattribute können in einer Methode mit self.name = value gesetzt werden. Sowohl auf Klassen- als auch auf Instanzattribute kann über die Notation self.name zugegriffen werden, wobei ein Instanzattribut ein Klassenattribut mit demselben Namen überdeckt, wenn auf diese Weise darauf zugegriffen wird. Klassenattribute können als Standardwerte für Instanzattribute verwendet werden, doch die Verwendung veränderbarer Werte kann zu unerwarteten Ergebnissen führen. Deskriptoren können verwendet werden, um Instanzvariablen mit unterschiedlichen Implementierungsdetails zu erstellen.
Siehe auch
- PEP 3115 - Metaklassen in Python 3000
Der Vorschlag, durch den die Deklaration von Metaklassen auf die aktuelle Syntax umgestellt wurde, sowie die Semantik hinsichtlich der Konstruktion von Klassen mit Metaklassen.
- PEP 3129 - Klassendekoratoren
Der Vorschlag, mit dem Klassendekoratoren eingeführt wurden. Funktions- und Methodendekoratoren wurden unter PEP 318 eingeführt.
8.9. Coroutinen¶
Added in version 3.5.
8.9.1. Definition einer Coroutine-Funktion¶
async_funcdef ::= [decorators] "async" "def"funcname"(" [parameter_list] ")" ["->"expression] ":"suite
Die Ausführung von Python-Coroutinen kann an vielen Stellen unterbrochen und wieder aufgenommen werden (siehe coroutine). await -Ausdrücke, async for und async with können nur im Körper einer Coroutine-Funktion verwendet werden.
Mit der Syntax async def definierte Funktionen sind immer Coroutinen, auch wenn sie die Schlüsselwörter await oder async nicht enthalten.
Es ist ein SyntaxError, einen yield from -Ausdruck im Körper einer Coroutine-Funktion zu verwenden.
Ein Beispiel für eine Coroutine-Funktion:
async def func(param1, param2):
do_stuff()
await some_coroutine()
Geändert in Version 3.7: await und async sind nun Schlüsselwörter; zuvor wurden sie nur innerhalb des Körpers einer Coroutine-Funktion als solche behandelt.
8.9.2. Die Anweisung async for¶
async_for_stmt ::= "async" for_stmt
Ein asynchrones Iterabel stellt eine Methode __aiter__ bereit, die direkt einen asynchronen Iterator zurückgibt, der in seiner Methode __anext__ asynchronen Code aufrufen kann.
Die Anweisung async for ermöglicht eine bequeme Iteration über asynchrone Iterables.
Der folgende Code:
async for TARGET in ITER:
SUITE
else:
SUITE2
Ist semantisch gleichbedeutend mit:
iter = (ITER).__aiter__()
running = True
while running:
try:
TARGET = await iter.__anext__()
except StopAsyncIteration:
running = False
else:
SUITE
else:
SUITE2
mit der Ausnahme, dass für __aiter__() und __anext__() die implizite Spezialmethoden-Suche verwendet wird.
Es ist ein SyntaxError, eine async for -Anweisung außerhalb des Körpers einer Coroutine-Funktion zu verwenden.
8.9.3. Die Anweisung async with¶
async_with_stmt ::= "async" with_stmt
Ein asynchroner Kontextmanager ist ein Kontextmanager, der die Ausführung in seinen enter- und exit-Methoden unterbrechen kann.
Der folgende Code:
async mit EXPRESSION als TARGET:
SUITE
ist semantisch gleichbedeutend mit:
manager = (EXPRESSION)
aenter = manager.__aenter__
aexit = manager.__aexit__
value = await aenter()
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not await aexit(*sys.exc_info()):
raise
finally:
if not hit_except:
await aexit(None, None, None)
mit der Ausnahme, dass für __aenter__() und __aexit__() die implizite Spezialmethoden-Suche verwendet wird.
Es ist ein SyntaxError, eine async with -Anweisung außerhalb des Körpers einer Coroutine-Funktion zu verwenden.
Siehe auch
- PEP 492 - Coroutinen mit der „async“- und „await“-Syntax
Der Vorschlag, durch den Coroutinen zu einem eigenständigen Konzept in Python wurden und die entsprechende Syntax hinzugefügt wurde.
8.10. Typenparameterlisten¶
Added in version 3.12.
Geändert in Version 3.13: Es wurde Unterstützung für Standardwerte hinzugefügt (siehe PEP 696).
type_params ::= "["type_param(","type_param)* "]" type_param ::=typevar|typevartuple|paramspectypevar ::=identifier(":"expression)? ("="expression)? typevartuple ::= "*"identifier("="expression)? paramspec ::= "**"identifier("="expression)?
Funktionen (einschließlich Coroutinen), Klassen und Typalias können eine Typ-Parameterliste enthalten:
def max[T](args: list[T]) -> T:
...
async def amax[T](args: list[T]) -> T:
...
class Bag[T]:
def __iter__(self) -> Iterator[T]:
...
def add(self, arg: T) -> None:
...
type ListOrSet[T] = list[T] | set[T]
Semantisch bedeutet dies, dass die Funktion, Klasse oder der Typalias über eine Typvariable generisch ist. Diese Information wird in erster Linie von statischen Typprüfern verwendet, und zur Laufzeit verhalten sich generische Objekte weitgehend wie ihre nicht-generischen Entsprechungen.
Typ-Parameter werden in eckigen Klammern ([]) unmittelbar nach dem Namen der Funktion, Klasse oder des Typ-Alias deklariert. Auf die Typ-Parameter kann innerhalb des Geltungsbereichs des generischen Objekts zugegriffen werden, anderswo jedoch nicht. Daher ist nach einer Deklaration def func[T](): pass der Name T im Modul-Geltungsbereich nicht verfügbar. Im Folgenden wird die Semantik generischer Objekte genauer beschrieben. Der Geltungsbereich von Typ-Parametern wird durch eine spezielle Funktion (technisch gesehen ein Annotationsbereich) modelliert, die die Erstellung des generischen Objekts umschließt.
Generische Funktionen, Klassen und Typaliasse verfügen über ein Attribut __type_params__, in dem ihre Typparameter aufgeführt sind.
Es gibt drei Arten von Typenparametern:
typing.TypeVar, eingeführt durch einen einfachen Namen (z. B.T). Semantisch gesehen stellt dies für einen Typprüfer einen einzelnen Typ dar.typing.TypeVarTuple, eingeführt durch einen Namen, dem ein einzelnes Sternchen vorangestellt ist (z. B.*Ts). Semantisch steht dies für ein Tupel beliebiger Typen.typing.ParamSpec, eingeleitet durch einen Namen, dem zwei Sternchen vorangestellt sind (z. B.**P). Semantisch gesehen steht dies für die Parameter eines aufrufbaren Objekts.
typing.TypeVar Deklarationen können Grenzen und Einschränkungen mit einem Doppelpunkt (:) definieren, auf den ein Ausdruck folgt. Ein einzelner Ausdruck nach dem Doppelpunkt bezeichnet eine Grenze (z. B. T: int). Semantisch bedeutet dies, dass die typing.TypeVar nur Typen darstellen kann, die ein Untertyp dieser Grenze sind. Ein in Klammern gesetztes Tupel von Ausdrücken nach dem Doppelpunkt bezeichnet eine Reihe von Einschränkungen (z. B. T: (str, bytes)). Jedes Element des Tupels sollte ein Typ sein (auch dies wird zur Laufzeit nicht erzwungen). Eingeschränkte Typvariablen können nur einen der Typen aus der Liste der Einschränkungen annehmen.
Bei typing.TypeVars, die unter Verwendung der Typ-Parameterlisten-Syntax deklariert wurden, werden die Grenzen und Einschränkungen nicht bei der Erstellung des generischen Objekts ausgewertet, sondern erst dann, wenn explizit über die Attribute __bound__ und __constraints__ auf den Wert zugegriffen wird. Zu diesem Zweck werden die Grenzen bzw. Einschränkungen in einem separaten Annotationsbereich ausgewertet.
typing.TypeVarTuples und typing.ParamSpecs dürfen keine Begrenzungen oder Einschränkungen aufweisen.
Alle drei Varianten von Typparametern können zudem einen Standardwert haben, der verwendet wird, wenn der Typparameter nicht explizit angegeben wird. Dieser wird durch Anhängen eines einzelnen Gleichheitszeichens (=), gefolgt von einem Ausdruck, hinzugefügt. Ähnlich wie die Grenzen und Einschränkungen von Typvariablen wird der Standardwert nicht bei der Erstellung des Objekts ausgewertet, sondern erst, wenn auf das Attribut __default__ des Typparameters zugegriffen wird. Zu diesem Zweck wird der Standardwert in einem separaten Annotationsbereich ausgewertet. Wenn für einen Typparameter kein Standardwert angegeben ist, wird das Attribut __default__ auf das spezielle Sentinel-Objekt typing.NoDefault gesetzt.
Das folgende Beispiel zeigt den vollständigen Satz zulässiger Typ-Parameter-Deklarationen:
def overly_generic[
SimpleTypeVar,
TypeVarWithDefault = int,
TypeVarWithBound: int,
TypeVarWithConstraints: (str, bytes),
*SimpleTypeVarTuple = (int, float),
**SimpleParamSpec = (str, bytearray),
](
a: SimpleTypeVar,
b: TypeVarWithDefault,
c: TypeVarWithBound,
d: Callable[SimpleParamSpec, TypeVarWithConstraints],
*e: SimpleTypeVarTuple,
): ...
8.10.1. Generische Funktionen¶
Generische Funktionen werden wie folgt deklariert:
def func[T](arg: T): ...
Diese Syntax entspricht folgendem:
annotation-def TYPE_PARAMS_OF_func():
T = typing.TypeVar("T")
def func(arg: T): ...
func.__type_params__ = (T,)
return func
func = TYPE_PARAMS_OF_func()
Hier bezeichnet annotation-def einen Annotationsbereich, der zur Laufzeit eigentlich an keinen Namen gebunden ist. (Bei der Übersetzung wurde noch eine weitere Freiheit in Anspruch genommen: Die Syntax greift nicht über Attributzugriff auf das Modul typing zu, sondern erstellt direkt eine Instanz von typing.TypeVar.)
Die Annotationen generischer Funktionen werden innerhalb des Annotationsbereichs ausgewertet, der für die Deklaration der Typparameter verwendet wird; die Standardwerte und Dekoratoren der Funktion hingegen nicht.
Das folgende Beispiel veranschaulicht die Gültigkeitsbereichsregeln für diese Fälle sowie für weitere Varianten von Typparametern:
@decorator
def func[T: int, *Ts, **P](*args: *Ts, arg: Callable[P, T] = some_default):
...
Abgesehen von der verzögerten Auswertung der Bindung TypeVar entspricht dies folgendem Ausdruck:
DEFAULT_OF_arg = some_default
annotation-def TYPE_PARAMS_OF_func():
annotation-def BOUND_OF_T():
return int
# Tatsächlich wird BOUND_OF_T() nur bei Bedarf ausgewertet.
T = typing.TypeVar("T", bound=BOUND_OF_T())
Ts = typing.TypeVarTuple("Ts")
P = typing.ParamSpec("P")
def func(*args: *Ts, arg: Callable[P, T] = DEFAULT_OF_arg):
...
func.__type_params__ = (T, Ts, P)
return func
func = decorator(TYPE_PARAMS_OF_func())
Die großgeschriebenen Namen wie DEFAULT_OF_arg werden zur Laufzeit eigentlich nicht gebunden.
8.10.2. Generische Klassen¶
Generische Klassen werden wie folgt deklariert:
Klasse Bag[T]: ...
Diese Syntax entspricht folgendem:
annotation-def TYPE_PARAMS_OF_Bag():
T = typing.TypeVar("T")
class Bag(typing.Generic[T]):
__type_params__ = (T,)
...
return Bag
Bag = TYPE_PARAMS_OF_Bag()
Auch hier weist annotation-def (kein echtes Schlüsselwort) auf einen Annotationsbereich hin, und der Name TYPE_PARAMS_OF_Bag wird zur Laufzeit tatsächlich nicht gebunden.
Generische Klassen erben implizit von typing.Generic. Die Basisklassen und Schlüsselwortargumente generischer Klassen werden innerhalb des Typbereichs für die Typparameter ausgewertet, während Dekoratoren außerhalb dieses Bereichs ausgewertet werden. Dies wird durch das folgende Beispiel veranschaulicht:
@decorator
class Bag(Base[T], arg=T): ...
Das entspricht folgendem:
annotation-def TYPE_PARAMS_OF_Bag():
T = typing.TypeVar("T")
class Bag(Base[T], typing.Generic[T], arg=T):
__type_params__ = (T,)
...
return Bag
Bag = decorator(TYPE_PARAMS_OF_Bag())
8.10.3. Generische Typaliase¶
Die Anweisung type kann auch zum Erstellen eines generischen Typalias verwendet werden:
Typ ListOrSet[T] = list[T] | set[T]
Abgesehen von der verzögerten Auswertung des Werts entspricht dies folgendem Ausdruck:
annotation-def TYPE_PARAMS_OF_ListOrSet():
T = typing.TypeVar("T")
annotation-def VALUE_OF_ListOrSet():
return list[T] | set[T]
# Tatsächlich wird der Wert verzögert ausgewertet
return typing.TypeAliasType("ListOrSet", VALUE_OF_ListOrSet(), type_params=(T,))
ListOrSet = TYPE_PARAMS_OF_ListOrSet()
Hier bezeichnet annotation-def (kein echtes Schlüsselwort) einen Annotationsbereich. Die großgeschriebenen Namen wie TYPE_PARAMS_OF_ListOrSet werden zur Laufzeit tatsächlich nicht gebunden.
Fußnoten