PEP 634 – Strukturelle Mustererkennung: Spezifikation
- Autor:
- Brandt Bucher <brandt at python.org>, Guido van Rossum <guido at python.org>
- BDFL-Delegate:
- Discussions-To:
- Python-Dev Liste
- Status:
- Final
- Typ:
- Standards Track
- Erstellt:
- 12. Sep. 2020
- Python-Version:
- 3.10
- Post-History:
- 22. Okt. 2020, 08. Feb. 2021
- Ersetzt:
- 622
- Resolution:
- Nachricht der Python-Committers
Zusammenfassung
Dieses PEP liefert die technische Spezifikation für die `match`-Anweisung. Es ersetzt PEP 622, das hiermit in drei Teile aufgeteilt wird
Dieses PEP ist absichtlich frei von Kommentaren; die Motivation und alle Erklärungen zu unseren Designentscheidungen finden Sie in PEP 635. Erstlesern wird empfohlen, mit PEP 636 zu beginnen, das eine sanftere Einführung in die Konzepte, Syntax und Semantik von Mustern bietet.
Syntax und Semantik
Siehe Anhang A für die vollständige Grammatik.
Überblick und Terminologie
Der Prozess der Mustererkennung nimmt als Eingabe ein Muster (nach case) und einen Subjektwert (nach match). Phrasen zur Beschreibung des Prozesses sind „das Muster wird mit dem Subjektwert abgeglichen“ und „wir gleichen das Muster mit dem Subjektwert ab“.
Das primäre Ergebnis der Mustererkennung ist Erfolg oder Misserfolg. Bei Erfolg können wir sagen: „Das Muster ist erfolgreich“, „Der Abgleich ist erfolgreich“ oder „Das Muster passt zum Subjektwert“.
In vielen Fällen enthält ein Muster Unterelemente, und Erfolg oder Misserfolg wird durch den Erfolg oder Misserfolg des Abgleichs dieser Unterelemente mit dem Wert (z. B. für ODER-Muster) oder mit Teilen des Werts (z. B. für Sequenzmuster) bestimmt. Dieser Prozess verarbeitet typischerweise die Unterelemente von links nach rechts, bis das Gesamtergebnis bestimmt ist. Z. B. ist ein ODER-Muster beim ersten erfolgreichen Unterelement erfolgreich, während ein Sequenzmuster beim ersten fehlschlagenden Unterelement fehlschlägt.
Ein sekundäres Ergebnis der Mustererkennung können eine oder mehrere Namensbindungen sein. Wir können sagen: „Das Muster bindet einen Wert an einen Namen“. Wenn Unterelemente bis zum ersten Erfolg versucht werden, sind nur die Bindungen des erfolgreichen Unterelements gültig; wenn bis zum ersten Misserfolg versucht wird, werden die Bindungen zusammengeführt. Mehrere weitere Regeln, die unten erläutert werden, gelten für diese Fälle.
Die Match-Anweisung
Syntax
match_stmt: "match" subject_expr ':' NEWLINE INDENT case_block+ DEDENT
subject_expr:
| star_named_expression ',' star_named_expressions?
| named_expression
case_block: "case" patterns [guard] ':' block
guard: 'if' named_expression
Die Regeln star_named_expression, star_named_expressions, named_expression und block sind Teil der Standard-Python-Grammatik.
Die Regel patterns wird unten spezifiziert.
Zur Information: match_stmt ist eine neue Alternative für compound_statement.
compound_statement:
| if_stmt
...
| match_stmt
Die Schlüsselwörter match und case sind weiche Schlüsselwörter, d. h. sie sind in anderen grammatikalischen Kontexten keine reservierten Wörter (einschließlich am Zeilenanfang, wenn keine erwartete Doppelpunkt vorhanden ist). Dies impliziert, dass sie nur als Teil einer `match`-Anweisung oder eines `case`-Blocks als Schlüsselwörter erkannt werden und in allen anderen Kontexten als Variablen- oder Argumentnamen verwendet werden dürfen.
Match-Semantik
Die `match`-Anweisung wertet zuerst den Subjektausdruck aus. Wenn ein Komma vorhanden ist, wird gemäß den Standardregeln ein Tupel konstruiert.
Der resultierende Subjektwert wird dann verwendet, um den ersten `case`-Block auszuwählen, dessen Muster ihn erfolgreich abgleichen *und* dessen Guard-Bedingung (falls vorhanden) „wahr“ ist. Wenn kein `case`-Block qualifiziert, ist die `match`-Anweisung abgeschlossen; andernfalls wird der Block des ausgewählten `case`-Blocks ausgeführt. Es gelten die üblichen Regeln für die Ausführung eines Blocks, der in eine zusammengesetzte Anweisung verschachtelt ist (z. B. eine `if`-Anweisung).
Namensbindungen, die während eines erfolgreichen Musterabgleichs vorgenommen werden, überdauern den ausgeführten Block und können nach der `match`-Anweisung verwendet werden.
Während fehlgeschlagener Musterabgleiche können einige Unterelemente erfolgreich sein. Beispielsweise kann beim Abgleich des Musters (0, x, 1) mit dem Wert [0, 1, 2] das Unterelement x erfolgreich sein, wenn die Listenelemente von links nach rechts abgeglichen werden. Die Implementierung kann wählen, ob sie persistente Bindungen für diese Teilabgleiche vornimmt oder nicht. Benutzercode, der eine `match`-Anweisung enthält, sollte sich nicht auf die Bindungen eines fehlgeschlagenen Abgleichs verlassen, aber auch nicht davon ausgehen, dass Variablen durch einen fehlgeschlagenen Abgleich unverändert bleiben. Dieser Teil des Verhaltens bleibt absichtlich undefiniert, damit verschiedene Implementierungen Optimierungen hinzufügen können und um semantische Einschränkungen zu vermeiden, die die Erweiterbarkeit dieser Funktion einschränken könnten.
Die genauen Regeln für Musterbindungen variieren je nach Mustertyp und werden unten spezifiziert.
Guards
Wenn ein Guard für einen `case`-Block vorhanden ist, wird nach erfolgreichem Abgleich des Musters oder der Muster im `case`-Block der Ausdruck im Guard ausgewertet. Wenn dieser eine Ausnahme auslöst, wird die Ausnahme weitergegeben. Andernfalls, wenn die Bedingung „wahr“ ist, wird der `case`-Block ausgewählt; wenn sie „falsch“ ist, wird der `case`-Block nicht ausgewählt.
Da Guards Ausdrücke sind, dürfen sie Seiteneffekte haben. Die Auswertung von Guards muss von der ersten bis zur letzten `case`-Klausel nacheinander erfolgen, wobei `case`-Klauseln übersprungen werden, deren Muster nicht alle erfolgreich sind. (Das heißt, selbst wenn die Bestimmung, ob diese Muster erfolgreich sind, außer Reihenfolge erfolgen kann, muss die Auswertung der Guards in Reihenfolge erfolgen.) Die Auswertung von Guards muss beendet werden, sobald ein `case`-Block ausgewählt wurde.
Irrefutable Case-Blöcke
Ein Muster gilt als *irrefutable* (nicht widerlegbar), wenn wir allein aus seiner Syntax beweisen können, dass es immer erfolgreich sein wird. Insbesondere sind Erfassungsmuster (`capture patterns`) und Wildcard-Muster (`wildcard patterns`) irrefutable, ebenso wie AS-Muster, deren linke Seite irrefutable ist, ODER-Muster, die mindestens ein irrefutable Muster enthalten, und geklammerte irrefutable Muster.
Ein `case`-Block gilt als irrefutable, wenn er keinen Guard hat und sein Muster irrefutable ist.
Eine `match`-Anweisung darf höchstens einen irrefutable `case`-Block haben, und dieser muss der letzte sein.
Muster
Die Top-Level-Syntax für Muster ist wie folgt:
patterns: open_sequence_pattern | pattern
pattern: as_pattern | or_pattern
as_pattern: or_pattern 'as' capture_pattern
or_pattern: '|'.closed_pattern+
closed_pattern:
| literal_pattern
| capture_pattern
| wildcard_pattern
| value_pattern
| group_pattern
| sequence_pattern
| mapping_pattern
| class_pattern
AS-Muster
Syntax
as_pattern: or_pattern 'as' capture_pattern
(Hinweis: Der Name auf der rechten Seite darf nicht _ sein.)
Ein AS-Muster gleicht das ODER-Muster links vom Schlüsselwort as mit dem Subjekt ab. Wenn dies fehlschlägt, schlägt das AS-Muster fehl. Andernfalls bindet das AS-Muster das Subjekt an den Namen rechts vom Schlüsselwort as und ist erfolgreich.
ODER-Muster
Syntax
or_pattern: '|'.closed_pattern+
Wenn zwei oder mehr Muster durch vertikale Striche (`|`) getrennt sind, spricht man von einem ODER-Muster. (Ein einzelnes geschlossenes Muster ist einfach das.)
Nur das letzte Unterelement darf irrefutable sein.
Jedes Unterelement muss dieselbe Menge an Namen binden.
Ein ODER-Muster gleicht nacheinander jedes seiner Unterelemente mit dem Subjekt ab, bis eines erfolgreich ist. Das ODER-Muster gilt dann als erfolgreich. Wenn keines der Unterelemente erfolgreich ist, schlägt das ODER-Muster fehl.
Literale Muster
Syntax
literal_pattern:
| signed_number
| signed_number '+' NUMBER
| signed_number '-' NUMBER
| strings
| 'None'
| 'True'
| 'False'
signed_number: NUMBER | '-' NUMBER
Die Regel strings und das Token NUMBER sind in der Standard-Python-Grammatik definiert.
Dreifach-geklammerte Strings werden unterstützt. Roh-Strings und Byte-Strings werden unterstützt. F-Strings werden nicht unterstützt.
Die Formen signed_number '+' NUMBER und signed_number '-' NUMBER sind nur zur Angabe von komplexen Zahlen erlaubt; sie erfordern eine reelle Zahl auf der linken Seite und eine imaginäre Zahl auf der rechten Seite.
Ein Literal-Muster ist erfolgreich, wenn der Subjektwert mit dem durch das Literal ausgedrückten Wert gleich verglichen wird, unter Verwendung der folgenden Vergleichsregeln:
- Zahlen und Strings werden mit dem Operator
==verglichen. - Die Singleton-Literale
None,TrueundFalsewerden mit dem Operatorisverglichen.
Erfassungsmuster
Syntax
capture_pattern: !"_" NAME
Der einzelne Unterstrich (`_`) ist kein Erfassungsmuster (das ist es, was `!"_"` ausdrückt). Er wird als Wildcard-Muster behandelt.
Ein Erfassungsmuster ist immer erfolgreich. Es bindet keinen Namen. Es bindet den Subjektwert an den Namen gemäß den Regeln für Namensbindungen, die für den Walross-Operator in PEP 572 festgelegt wurden. (Zusammenfassung: Der Name wird zu einer lokalen Variable im nächstgelegenen umgebenden Funktionsbereich, es sei denn, es gibt eine anwendbare nonlocal- oder global-Anweisung.)
In einem gegebenen Muster darf ein bestimmter Name nur einmal gebunden werden. Dies verbietet z. B. case x, x: ..., erlaubt aber case [x] | x: ....
Wildcard-Muster
Syntax
wildcard_pattern: "_"
Ein Wildcard-Muster ist immer erfolgreich. Es bindet keinen Namen.
Wertmuster
Syntax
value_pattern: attr
attr: name_or_attr '.' NAME
name_or_attr: attr | NAME
Der Punkt-Name im Muster wird mithilfe der Standardregeln zur Namensauflösung in Python nachgeschlagen. Wenn jedoch dasselbe Wertemuster mehrmals in derselben `match`-Anweisung vorkommt, kann der Interpreter den ersten gefundenen Wert zwischenspeichern und wiederverwenden, anstatt denselben Lookup zu wiederholen. (Zur Klarstellung: Dieser Cache ist streng an eine bestimmte Ausführung einer bestimmten `match`-Anweisung gebunden.)
Das Muster ist erfolgreich, wenn der gefundene Wert mit dem Subjektwert gleich verglichen wird (unter Verwendung des Operators ==).
Gruppenmuster
Syntax
group_pattern: '(' pattern ')'
(Siehe Muster oben für die Syntax von pattern. Beachten Sie, dass sie keine Kommas enthält – eine geklammerte Reihe von Elementen mit mindestens einem Komma ist ein Sequenzmuster, ebenso wie ().)
Ein geklammertes Muster hat keine zusätzliche Syntax. Es ermöglicht Benutzern, Klammern um Muster zu setzen, um die beabsichtigte Gruppierung zu betonen.
Sequenzmuster
Syntax
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 | pattern
star_pattern: '*' (capture_pattern | wildcard_pattern)
(Beachten Sie, dass ein einzelnes geklammertes Muster ohne nachfolgendes Komma ein Gruppierungsmuster und kein Sequenzmuster ist. Ein einzelnes Muster, das in [...] eingeschlossen ist, ist jedoch immer noch ein Sequenzmuster.)
Es gibt keinen semantischen Unterschied zwischen einem Sequenzmuster, das [...] verwendet, einem Sequenzmuster, das (...) verwendet, und einem offenen Sequenzmuster.
Ein Sequenzmuster kann höchstens ein Stern-Unterelement enthalten. Das Stern-Unterelement kann sich an jeder Position befinden. Wenn kein Stern-Unterelement vorhanden ist, ist das Sequenzmuster ein Sequenzmuster mit fester Länge; andernfalls ist es ein Sequenzmuster mit variabler Länge.
Damit ein Sequenzmuster erfolgreich ist, muss das Subjekt eine Sequenz sein, wobei eine Sequenz als ihre Klasse definiert ist als eine der folgenden:
- eine Klasse, die von
collections.abc.Sequenceerbt - eine Python-Klasse, die als
collections.abc.Sequenceregistriert wurde - eine eingebaute Klasse, deren Bit
Py_TPFLAGS_SEQUENCEgesetzt ist - eine Klasse, die von einer der oben genannten erbt (einschließlich Klassen, die *vor* der Registrierung einer übergeordneten Klasse als
Sequencedefiniert wurden)
Die folgenden Klassen der Standardbibliothek haben ihr Bit Py_TPFLAGS_SEQUENCE gesetzt:
array.arraycollections.dequelistmemoryviewrangetuple
Hinweis
Obwohl str, bytes und bytearray üblicherweise als Sequenzen betrachtet werden, sind sie nicht in der obigen Liste enthalten und stimmen nicht mit Sequenzmustern überein.
Ein Sequenzmuster fester Länge schlägt fehl, wenn die Länge der Subjektsequenz nicht gleich der Anzahl der Unterelemente ist.
Ein Sequenzmuster variabler Länge schlägt fehl, wenn die Länge der Subjektsequenz kleiner ist als die Anzahl der Nicht-Stern-Unterelemente.
Die Länge der Subjektsequenz wird mit der eingebauten Funktion len() ermittelt (d. h. über das __len__-Protokoll). Der Interpreter kann diesen Wert jedoch auf ähnliche Weise zwischenspeichern wie für Wertemuster beschrieben.
Ein Sequenzmuster fester Länge gleicht die Unterelemente mit den entsprechenden Elementen der Subjektsequenz von links nach rechts ab. Der Abgleich stoppt (mit einem Fehler), sobald ein Unterelement fehlschlägt. Wenn alle Unterelemente erfolgreich mit ihrem entsprechenden Element abgeglichen werden, ist das Sequenzmuster erfolgreich.
Ein Sequenzmuster variabler Länge gleicht zuerst die führenden Nicht-Stern-Unterelemente mit den entsprechenden Elementen der Subjektsequenz ab, wie bei einem Sequenzmuster fester Länge. Wenn dies erfolgreich ist, gleicht das Stern-Unterelement eine Liste ab, die aus den verbleibenden Subjekt-Elementen besteht, wobei Elemente vom Ende entfernt werden, die den Nicht-Stern-Unterelementen nach dem Stern-Unterelement entsprechen. Die verbleibenden Nicht-Stern-Unterelemente werden dann mit den entsprechenden Subjekt-Elementen abgeglichen, wie bei einem Sequenzmuster fester Länge.
Abgleichmuster
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
(Beachten Sie, dass **_ durch diese Syntax nicht zulässig ist.)
Ein Mapping-Muster kann höchstens ein Doppelstern-Muster enthalten, und dieses muss das letzte sein.
Ein Mapping-Muster darf keine doppelten Schlüsselwerte enthalten. (Wenn alle Schlüsselmuster Literal-Muster sind, wird dies als Syntaxfehler betrachtet; andernfalls ist dies ein Laufzeitfehler und löst ValueError aus.)
Damit ein Mapping-Muster erfolgreich ist, muss das Subjekt ein Mapping sein, wobei ein Mapping als seine Klasse definiert ist als eine der folgenden:
- eine Klasse, die von
collections.abc.Mappingerbt - eine Python-Klasse, die als
collections.abc.Mappingregistriert wurde - eine eingebaute Klasse, deren Bit
Py_TPFLAGS_MAPPINGgesetzt ist - eine Klasse, die von einer der oben genannten erbt (einschließlich Klassen, die *vor* der Registrierung einer übergeordneten Klasse als
Mappingdefiniert wurden)
Die Klassen der Standardbibliothek dict und mappingproxy haben ihr Bit Py_TPFLAGS_MAPPING gesetzt.
Ein Mapping-Muster ist erfolgreich, wenn jeder im Mapping-Muster angegebene Schlüssel in dem Subjekt-Mapping vorhanden ist und das Muster für jeden Schlüssel mit dem entsprechenden Element des Subjekt-Mappings übereinstimmt. Schlüssel werden immer mit dem Operator == verglichen. Wenn eine Form '**' NAME vorhanden ist, wird dieser Name an ein dict gebunden, das die verbleibenden Schlüssel-Wert-Paare aus dem Subjekt-Mapping enthält.
Wenn doppelte Schlüssel im Mapping-Muster erkannt werden, gilt das Muster als ungültig und es wird ein ValueError ausgelöst.
Schlüssel-Wert-Paare werden mit der Zwei-Argument-Form der get()-Methode des Subjekts abgeglichen. Infolgedessen müssen abgeglichene Schlüssel-Wert-Paare bereits im Mapping vorhanden sein und dürfen nicht zur Laufzeit durch __missing__ oder __getitem__ erstellt werden. Zum Beispiel werden Instanzen von collections.defaultdict nur von Mustern mit Schlüsseln abgeglichen, die bereits vorhanden waren, als die `match`-Anweisung gestartet wurde.
Klassenmuster
Syntax
class_pattern:
| name_or_attr '(' [pattern_arguments ','?] ')'
pattern_arguments:
| positional_patterns [',' keyword_patterns]
| keyword_patterns
positional_patterns: ','.pattern+
keyword_patterns: ','.keyword_pattern+
keyword_pattern: NAME '=' pattern
Ein Klassenmuster darf dasselbe Schlüsselwort nicht mehrmals wiederholen.
Wenn name_or_attr keine Instanz des eingebauten type ist, wird TypeError ausgelöst.
Ein Klassenmuster schlägt fehl, wenn das Subjekt keine Instanz von name_or_attr ist. Dies wird mit isinstance() getestet.
Wenn keine Argumente vorhanden sind, ist das Muster erfolgreich, wenn die isinstance()-Prüfung erfolgreich ist. Andernfalls:
- Wenn nur Schlüsselwortmuster vorhanden sind, werden diese nacheinander wie folgt verarbeitet:
- Das Schlüsselwort wird als Attribut des Subjekts nachgeschlagen.
- Wenn dies eine andere Ausnahme als
AttributeErrorauslöst, wird die Ausnahme weitergegeben. - Wenn dies
AttributeErrorauslöst, schlägt das Klassenmuster fehl. - Andernfalls wird das Muster, das mit dem Schlüsselwort verbunden ist, mit dem Attributwert abgeglichen. Wenn dies fehlschlägt, schlägt das Klassenmuster fehl. Wenn es erfolgreich ist, wird der Abgleich mit dem nächsten Schlüsselwort fortgesetzt.
- Wenn dies eine andere Ausnahme als
- Wenn alle Schlüsselwortmuster erfolgreich sind, ist das Klassenmuster als Ganzes erfolgreich.
- Das Schlüsselwort wird als Attribut des Subjekts nachgeschlagen.
- Wenn Positionsmuster vorhanden sind, werden diese in Schlüsselwortmuster umgewandelt (siehe unten) und als zusätzliche Schlüsselwortmuster behandelt, die den syntaktischen Schlüsselwortmustern (falls vorhanden) vorangestellt sind.
Positionsmuster werden mithilfe des __match_args__-Attributs der durch name_or_attr bezeichneten Klasse wie folgt in Schlüsselwortmuster umgewandelt:
- Für eine Reihe von eingebauten Typen (unten spezifiziert) wird ein einzelnes Positions-Unterelement akzeptiert, das das gesamte Subjekt abgleicht. (Schlüsselwortmuster funktionieren hier wie für andere Typen.)
- Das Äquivalent von
getattr(cls, "__match_args__", ()))wird aufgerufen. - Wenn dies eine Ausnahme auslöst, wird die Ausnahme weitergegeben.
- Wenn der zurückgegebene Wert kein Tupel ist, schlägt die Konvertierung fehl und es wird
TypeErrorausgelöst. - Wenn es mehr Positionsmuster gibt als die Länge von
__match_args__(ermittelt durchlen()), wirdTypeErrorausgelöst. - Andernfalls wird das Positionsmuster
imithilfe von__match_args__[i]als Schlüsselwort in ein Schlüsselwortmuster umgewandelt, vorausgesetzt, letzteres ist ein String; wenn dies nicht der Fall ist, wirdTypeErrorausgelöst. - Bei doppelten Schlüsselwörtern wird
TypeErrorausgelöst.
Sobald die Positionsmuster in Schlüsselwortmuster umgewandelt wurden, wird der Abgleich fortgesetzt, als ob es nur Schlüsselwortmuster gäbe.
Wie oben erwähnt, ist die Handhabung von Positions-Unterelementen für die folgenden eingebauten Typen unterschiedlich: bool, bytearray, bytes, dict, float, frozenset, int, list, set, str und tuple.
Dieses Verhalten ist ungefähr äquivalent zu folgendem:
class C:
__match_args__ = ("__match_self_prop__",)
@property
def __match_self_prop__(self):
return self
Seiteneffekte und undefiniertes Verhalten
Der einzige explizit durch den Abgleichprozess verursachte Seiteneffekt ist die Bindung von Namen. Der Prozess stützt sich jedoch auf Attributzugriff, Instanzprüfungen, len(), Gleichheit und Elementzugriff auf das Subjekt und einige seiner Komponenten. Er wertet auch Wertemuster und die Klasse von Klassenmustern aus. Obwohl keiner dieser Vorgänge normalerweise Seiteneffekte erzeugt, können sie theoretisch welche haben. Dieser Vorschlag lässt absichtlich jede Spezifikation darüber aus, welche Methoden aufgerufen werden oder wie oft. Dieses Verhalten ist daher undefiniert, und Benutzercode sollte sich nicht darauf verlassen.
Ein weiteres undefiniertes Verhalten ist die Bindung von Variablen durch Erfassungsmuster, denen (im selben `case`-Block) ein anderes Muster folgt, das fehlschlägt. Diese können früher oder später auftreten, abhängig von der Implementierungsstrategie. Die einzige Einschränkung ist, dass Erfassungsvariablen gesetzt werden müssen, bevor Guards, die sie explizit verwenden, ausgewertet werden. Wenn ein Guard aus einer and-Klausel besteht, kann die Auswertung der Operanden sogar mit der Mustererkennung durchsetzt werden, solange die Auswertungsreihenfolge von links nach rechts beibehalten wird.
Die Standardbibliothek
Um die Verwendung der Mustererkennung zu erleichtern, werden mehrere Änderungen an der Standardbibliothek vorgenommen:
- Namedtuples und Dataclasses erhalten automatisch generierte
__match_args__. - Für Dataclasses entspricht die Reihenfolge der Attribute in den generierten
__match_args__der Reihenfolge der entsprechenden Argumente in der generierten__init__()-Methode. Dies schließt Situationen ein, in denen Attribute von einer Oberklasse geerbt werden. Felder mitinit=Falsesind von__match_args__ausgeschlossen.
Darüber hinaus wird eine systematische Anstrengung unternommen, bestehende Klassen der Standardbibliothek durchzugehen und __match_args__ hinzuzufügen, wo dies vorteilhaft erscheint.
Anhang A – Vollständige Grammatik
Hier ist die vollständige Grammatik für match_stmt. Dies ist eine zusätzliche Alternative für compound_stmt. Denken Sie daran, dass match und case weiche Schlüsselwörter sind, d. h. sie sind in anderen grammatikalischen Kontexten keine reservierten Wörter (einschließlich am Zeilenanfang, wenn keine erwartete Doppelpunkt vorhanden ist). Konventionsgemäß verwenden harte Schlüsselwörter einfache Anführungszeichen, während weiche Schlüsselwörter doppelte Anführungszeichen verwenden.
Andere verwendete Notation über die Standard-EBNF hinaus:
SEP.RULE+ist eine Abkürzung fürRULE (SEP RULE)*!RULEist eine negative Lookahead-Assertion
match_stmt: "match" subject_expr ':' NEWLINE INDENT case_block+ DEDENT
subject_expr:
| star_named_expression ',' [star_named_expressions]
| named_expression
case_block: "case" patterns [guard] ':' block
guard: 'if' named_expression
patterns: open_sequence_pattern | pattern
pattern: as_pattern | or_pattern
as_pattern: or_pattern 'as' capture_pattern
or_pattern: '|'.closed_pattern+
closed_pattern:
| literal_pattern
| capture_pattern
| wildcard_pattern
| value_pattern
| group_pattern
| sequence_pattern
| mapping_pattern
| class_pattern
literal_pattern:
| signed_number !('+' | '-')
| signed_number '+' NUMBER
| signed_number '-' NUMBER
| strings
| 'None'
| 'True'
| 'False'
signed_number: NUMBER | '-' NUMBER
capture_pattern: !"_" NAME !('.' | '(' | '=')
wildcard_pattern: "_"
value_pattern: attr !('.' | '(' | '=')
attr: name_or_attr '.' NAME
name_or_attr: attr | NAME
group_pattern: '(' pattern ')'
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 | pattern
star_pattern: '*' (capture_pattern | wildcard_pattern)
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
class_pattern:
| name_or_attr '(' [pattern_arguments ','?] ')'
pattern_arguments:
| positional_patterns [',' keyword_patterns]
| keyword_patterns
positional_patterns: ','.pattern+
keyword_patterns: ','.keyword_pattern+
keyword_pattern: NAME '=' pattern
Urheberrecht
Dieses Dokument wird in die Public Domain oder unter die CC0-1.0-Universal-Lizenz gestellt, je nachdem, welche Lizenz permissiver ist.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0634.rst
Letzte Änderung: 2023-12-11 05:40:56 GMT