Structural-Pattern-Matching wird unter Pythonistas als vielleicht wichtigste – wenn auch kontroverse – Ergänzung der Sprachsyntax seit async gehandelt. Die mit Python 3.10 eingeführte Neuerung ist das Ergebnis des Versuchs, die aus anderen Programmiersprachen bekannte switch...case
-Syntax in Python einzuführen, bietet dabei aber zusätzlich eine Reihe von Möglichkeiten, die über das Vorbild hinausgehen.
Pythons Syntax wurde um die match...case
-Struktur erweitert. Wie die Switch/Case-Struktur anderer Sprachen ermöglicht Structural-Pattern-Matching es, eine Variable mit einem Satz möglicher Werte abzugleichen. match...case
fungiert in seiner einfachsten Form quasi als Ersatz für eine if-else-
Struktur:
http_code = "418"
if http_code == "200":
print("OK")
elif http_code == "404":
print("Not Found")
elif http_code == "418":
print("Dogs are cool")
else:
print("Code not found")
# Dogs are cool
die unter Verwendung des match
-Keywords auch so geschrieben werden könnte:
http_code = "418"
match http_code:
case "200":
print("Ok")
case "404":
print("Not Found")
case "418":
print("Dogs are cool")
case _:
print("Code not found")
# Dogs are cool
Die Möglichkeit einer cleaneren Notation ist es allerdings nicht, was das Feature so interessant macht. Structural-Pattern-Matching erlaubt es, die Struktur von Vergleichsobjekten mit einem oder mehreren Mustern abzugleichen. Zur Illustration zeigt das folgende Beispiel den Musterabgleich von zwei Dictionaries. Dictionaries oder Mapping-Strukturen im Allgemeinen sind eine der wichtigsten und gängigsten Datenstrukturen in Python.
Beide Dictionaries haben unterschiedlichen Strukturen:
In [1]:
dict_a = {
'id': 1,
'meta': {
'source': 'x',
'location': 'south'
}
}
und
In [2]:
dict_b = {
'id': 2,
'source': 'y',
'location': 'south'
}
Für beide lässt sich jeweils ein Pattern identifizieren:
#a
{
'id': int,
'meta': {'source': str,
'location': str}
}
und
#b
{
'id': int,
'source': str,
'location': str
}
Beide lassen sich dann in ein match...case
-Statement verpacken:
for d in [dict_a, dict_b, 'test']:
match d:
case {'id': ident,
'meta': {'source': source,
'location': loc}}:
print(ident, source, loc)
case {'id': ident,
'source': source,
'location': loc}:
print(ident, source, loc)
case _:
print('no match')
Außer Dictionaries können auch Sequenzen (Tupel oder Listen), primitive Datentypen oder Klasseninstanzen abgeglichen werden. Eine umfassende Liste der unterschiedlichen Patterns bietet die Doku (PEP 635). Gerade zur Datenverarbeitung könnte sich Structural-Pattern-Matching als echter Game-Changer erweisen. Wer tiefer einsteigen will, findet beispielsweise in diesem Video weitere Erläuterungen.