Struktureller Musterabgleich in Python
- Einführung in den strukturellen Musterabgleich und seine Bedeutung
- Verwenden Sie den strukturellen Musterabgleich in Python
Vor Python 3.10 hatten wir keine eingebaute Möglichkeit, den strukturellen Musterabgleich zu verwenden, der in anderen Programmiersprachen als switch-case
bezeichnet wird. Ab der Version Python 3.10 können wir die Anweisung match ... case
nicht verwenden, um die Anweisung switch ... case
zu emulieren.
Dieses Tutorial stellt den strukturellen Musterabgleich und seine Bedeutung in Python vor. Es verwendet auch verschiedene Muster, um die Verwendung der Anweisung match ... case
zu demonstrieren.
Einführung in den strukturellen Musterabgleich und seine Bedeutung
Ab Anfang 2021 konnten wir das Schlüsselwort match
in veröffentlichten Python-Versionen kleiner oder gleich 3.9 nicht verwenden. Damals waren wir es gewohnt, switch ... case
mit einem Wörterbuch oder verschachtelten if/elif/else
-Anweisungen zu simulieren.
Aber Python 3.10 hat eine neue Funktion eingeführt, die als struktureller Musterabgleich bekannt ist (match ... case
-Anweisung). Es entspricht einer switch ... case
-Anweisung, wie wir sie in Java, C++ und vielen anderen Programmiersprachen haben.
Diese neue Funktion hat es uns ermöglicht, einfache, leicht lesbare und minimal anfällige Anweisungen zur Fehlerflusskontrolle zu schreiben.
Verwenden Sie den strukturellen Musterabgleich in Python
Der strukturelle Musterabgleich wird als switch ... case
-Anweisung verwendet und ist leistungsfähiger als diese. Wie? Sehen wir uns unten einige Beispiele an, um ihre Verwendung in verschiedenen Situationen zu erfahren.
Grundlegende Verwendung der Anweisung match ... case
Beispielcode:
# >= Python 3.10
colour = "blue"
match colour:
case "green":
print("The specified colour is green")
case "white":
print("Wow, you've picked white")
case "green":
print("Great, you are going with green colour")
case "blue":
print("Blue like sky...")
AUSGANG:
Blue like sky...
Hier haben wir zunächst eine Variable Farbe
, die Blau
enthält. Dann verwenden wir das Schlüsselwort match
, das den Wert der Variable color
mit verschiedenen angegebenen Fällen abgleicht, wobei jeder Fall mit dem Schlüsselwort case
beginnt, gefolgt von einem Muster, das wir vergleichen oder überprüfen möchten.
Das Muster kann eines der folgenden sein:
- wörtliches Muster
- Erfassungsmuster
- Platzhaltermuster
- konstantes Wertmuster
- Sequenzmuster
- Zuordnungsmuster
- Klassenmuster
- ODER-Muster
- Walrossmuster
Die Anweisung match ... case
führt den Code nur unter dem ersten übereinstimmenden case
aus.
Was ist, wenn kein Fall
zugeordnet ist? Wie wird der Benutzer davon erfahren? Dafür können wir einen standardmäßigen Fall
wie folgt haben.
Beispielcode:
# >= Python 3.10
colour = "yellow"
match colour:
case "green":
print("The specified colour is green")
case "white":
print("Wow, you've picked white")
case "green":
print("Great, you are going with green colour")
case "blue":
print("Blue like sky...")
case other:
print("No match found!")
AUSGANG:
No match found!
Verwenden Sie match ... case
, um Datenstrukturen zu erkennen und zu dekonstruieren
Beispielcode:
# >= Python 3.10
student = {"name": {"first": "Mehvish", "last": "Ashiq"}, "section": "B"}
match student:
case {"name": {"first": firstname}}:
print(firstname)
AUSGANG:
Mehvish
Im obigen Beispiel ist der strukturelle Musterabgleich in den folgenden zwei Codezeilen in Aktion:
# >= Python 3.10
match student:
case {"name": {"first": firstname}}:
Wir verwenden die Anweisung match ... case
, um den Vornamen des Studenten zu finden, indem wir ihn aus der Datenstruktur student
extrahieren. Hier ist der Schüler
ein Wörterbuch, das die Informationen des Schülers enthält.
Die case
-Zeile gibt unser Muster an, um dem student
zu entsprechen. Unter Berücksichtigung des obigen Beispiels suchen wir nach einem Wörterbuch mit dem Schlüssel Name
, dessen Wert ein neues Wörterbuch ist.
Dieses verschachtelte Wörterbuch enthält einen "first"
-Schlüssel, dessen Wert an die firstname
-Variable gebunden ist. Schließlich verwenden wir die Variable firstname
, um den Wert auszudrucken.
Wir haben das Abbildungsmuster hier gelernt, wenn Sie es genauer beobachten. Wie? Das Zuordnungsmuster sieht wie folgt aus: {"student": s, "emails": [*es]}
, was der Zuordnung mit mindestens einem Satz angegebener Schlüssel entspricht.
Wenn alle Untermuster mit ihren entsprechenden Werten übereinstimmen, dann bindet es, was auch immer ein Untermuster während des Abgleichs mit Werten bindet, die den Schlüsseln entsprechen. Wenn wir das Erfassen der zusätzlichen Elemente zulassen möchten, können wir am Ende des Musters **rest
hinzufügen.
Verwenden Sie match ... case
mit dem Capture Pattern & Sequence Pattern
Beispielcode:
# >= Python 3.10
def sum_list_of_numbers(numbers):
match numbers:
case []:
return 0
case [first, *rest]:
return first + sum_list_of_numbers(rest)
sum_list_of_numbers([1, 2, 3, 4])
AUSGANG:
10
Hier verwenden wir die rekursive Funktion, um das Erfassungsmuster zu verwenden, um die Übereinstimmung mit dem angegebenen Muster zu erfassen und an den Namen zu binden.
In diesem Codebeispiel gibt der erste case
als Summe 0
zurück, wenn er mit einer leeren Liste übereinstimmt. Der zweite Fall
verwendet das Sequenzmuster mit zwei Erfassungsmustern, um die Listen mit einem von mehreren Elementen/Elementen abzugleichen.
Hier wird das erste Element in einer Liste erfasst und an den ersten
Namen gebunden, während das zweite Erfassungsmuster, *rest
, die Entpackungssyntax verwendet, um eine beliebige Anzahl von Elementen/Elementen abzugleichen.
Beachten Sie, dass der rest
an die Liste gebunden ist, die alle Elemente/Elemente von Zahlen enthält, mit Ausnahme des ersten. Um die Ausgabe zu erhalten, rufen wir die Funktion sum_list_of_numbers()
auf, indem wir eine Liste von Zahlen wie oben angegeben übergeben.
Verwenden Sie match ... case
mit dem Wildcard-Muster
Beispielcode:
# >= Python 3.10
def sum_list_of_numbers(numbers):
match numbers:
case []:
return 0
case [first, *rest]:
return first + sum_list_of_numbers(rest)
case _:
incorrect_type = numbers.__class__.__name__
raise ValueError(
f"Incorrect Values. We Can only Add lists of numbers,not {incorrect_type!r}"
)
sum_list_of_numbers({"1": "2", "3": "4"})
AUSGANG:
ValueError: Incorrect Values. We Can only Add lists of numbers, not 'dict'
Wir haben das Konzept der Verwendung des Wildcard-Musters gelernt, während wir die grundlegende Verwendung der Anweisung match ... case
gelernt haben, aber den Begriff des Wildcard-Musters dort nicht eingeführt. Stellen Sie sich ein Szenario vor, in dem die ersten beiden Fälle nicht übereinstimmen und wir als letzten Fall
ein Catchall-Muster benötigen.
Beispielsweise möchten wir einen Fehler auslösen, wenn wir anstelle einer Liste eine andere Art von Datenstruktur erhalten. Hier können wir _
als Platzhaltermuster verwenden, das mit allem übereinstimmt, ohne an den Namen gebunden zu sein. Wir fügen in diesem letzten Fall
eine Fehlerbehandlung hinzu, um den Benutzer zu informieren.
Was sagen Sie? Passt unser Muster gut dazu? Testen wir es, indem wir die Funktion sum_list_of_numbers()
aufrufen, indem wir eine Liste von String-Werten wie folgt übergeben:
sum_list_of_numbers(["1", "2", "3", "4"])
Es wird den folgenden Fehler erzeugen:
TypeError: can only concatenate str (not "int") to str
Wir können also sagen, dass das Muster immer noch nicht narrensicher genug ist. Warum? Weil wir eine Datenstruktur vom Typ Liste an die Funktion sum_list_of_numbers()
übergeben, aber Werte vom Typ String haben, nicht wie erwartet den Typ Int.
Lesen Sie den folgenden Abschnitt, um zu erfahren, wie Sie es beheben können.
Verwenden Sie match ... case
mit dem Klassenmuster
Beispielcode:
# >= Python 3.10
def sum_list_of_numbers(numbers):
match numbers:
case []:
return 0
case [int(first), *rest]:
return first + sum_list_of_numbers(rest)
case _:
raise ValueError(f"Incorrect values! We can only add lists of numbers")
sum_list_of_numbers(["1", "2", "3", "4"])
AUSGANG:
ValueError: Incorrect values! We can only add lists of numbers
Der Basisfall (der erste Fall
) gibt 0
zurück; Daher funktioniert das Summieren nur für die Typen, die wir mit Zahlen addieren können. Beachten Sie, dass Python nicht weiß, wie man Textzeichenfolgen und Zahlen hinzufügt.
Wir können also das Klassenmuster verwenden, um unser Muster so einzuschränken, dass es nur mit ganzen Zahlen übereinstimmt. Das Klassenmuster ähnelt dem Zuordnungsmuster, entspricht aber den Attributen anstelle der Schlüssel.
Verwenden Sie match ... case
mit dem ODER-Muster
Beispielcode:
# >= Python 3.10
def sum_list_of_numbers(numbers):
match numbers:
case []:
return 0
case [int(first) | float(first), *rest]:
return first + sum_list_of_numbers(rest)
case _:
raise ValueError(f"Incorrect values! We can only add lists of numbers")
Angenommen, wir möchten, dass die Funktion sum_list_of_numbers()
für eine Liste von Werten funktioniert, unabhängig davon, ob es sich um Werte vom Typ Int oder Float handelt. Wir verwenden das ODER-Muster, dargestellt durch ein Pipe-Zeichen (|
).
Der obige Code muss den ValueError
auslösen, wenn die angegebene Liste andere Werte als Werte vom Typ int oder float enthält. Lassen Sie uns unter Berücksichtigung aller drei Szenarien testen.
Test 1: Übergeben Sie eine Liste mit Werten vom Typ int:
sum_list_of_numbers([1, 2, 3, 4]) # output is 10
Test 2: Übergeben Sie eine Liste mit Float-Werten:
sum_list_of_numbers([1.0, 2.0, 3.0, 4.0]) # output is 10.0
Test 3: Führen Sie eine Liste mit einem beliebigen anderen Typ außer den Typen int und float durch:
sum_list_of_numbers(["1", "2", "3", "4"])
# output is ValueError: Incorrect values! We can only add lists of numbers
Wie Sie sehen können, funktioniert die Funktion sum_list_of_numbers()
aufgrund der Verwendung des OR-Musters sowohl für int- als auch für Float-Werte.
Verwenden Sie match ... case
mit dem Literal Pattern
Beispielcode:
# >= Python 3.10
def say_hello(name):
match name:
case "Mehvish":
print(f"Hi, {name}!")
case _:
print("Howdy, stranger!")
say_hello("Mehvish")
AUSGANG:
Hi, Mehvish!
Dieses Beispiel verwendet ein Literalmuster, das mit dem Literalobjekt übereinstimmt, beispielsweise eine explizite Zahl oder Zeichenfolge, wie wir es bereits getan haben, als wir die grundlegende Verwendung der Anweisung match ... case
gelernt haben.
Es ist die grundlegendste Art von Muster und lässt uns eine switch ... case
-Anweisung ähnlich wie Java, C++ und andere Programmiersprachen simulieren. Sie können diese Seite besuchen, um mehr über alle Muster zu erfahren.