Wann "match/case" in Python?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Dennis89
User
Beiträge: 1037
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo zusammen,

seit Python 3.10 wird 'match/case' unterstützt.

Auf der Suche nach dem Sinn bzw. den Vorteilen davon, habe ich im Internet ein paar Beispiele gefunden, unter anderem sowas:
https://stackoverflow.com/questions/679 ... -in-python

Macht auf mich einen recht coolen Eindruck. Ich weis ja das einige von euch übere Jahrzente professionel mit Python programmieren und ich versuche so viel wie Möglich Code-Beispiele hier im Forum zu lesen, aber "match/case" ist mir nicht in Erinnerung geblieben.

Gibt es dafür einen Grund? Nutzt ihr das auch beruflich gar nicht? Wenn nein, wieso? Sind die Fragen bzw. Codebeispiele hier im Forum einfach zu simple?

Sorry für die Zeile bestehend aus lauter Fragen :mrgreen:

Würde mich freuen wenn ihr mir ein bisschen was darüber erzählen könnt.


Vielen Dank schon einmal!

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
noisefloor
User
Beiträge: 3723
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

`match..case` gibt es ja erst seit ca. 2 Jahren, von daher wird man da jetzt halt nicht so viele Bespiele finden.

Die Anzahl der Fälle, wo `match..case` sinnvoll ist, sind IMHO nicht so gängig bzw. vielleicht eher bei Leuten gängig, die Support brauchen. `match..case` ist ja _kein_ Ersatz für eine `if..elif..else` Kaskade.

IMHO ist es in den Release Notes von Python 3.10 ganz gut und ausführlich erklärt (Link).

Für mich als Hobbyprogrammierer reicht es zu wissen, dass es das gibt und was es kann. Mir fällt aber spontan für mich in den 15+ Jahren, wo ich Python benutze, ein Fall für das was ich programmiert habe ein, wo ich `match..case` vermisst habe. Was _nicht_ heißt, dass `match..case` sinnlos ist, sondern es einfach nicht so viele Situationen gibt, wo man das gewinnbringend nutzen kann.

Gruß, noisefloor
Benutzeravatar
snafu
User
Beiträge: 6681
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

BlackJack hatte vor einigen Wochen mal ein interessantes Beispiel gebracht, wo match..case verwendet wurde. Und zwar wirklich im Sinne von Pattern Matching, so wie es ja auch gedacht ist. Es ist ja gerade *kein* nachgebautes switch-Konstrukt aus C, sondern geht quasi 2 Schritte darüber hinaus.

Ob Python das jetzt unbedingt brauchte, wird sich im Laufe der Zeit zeigen, denke ich. So einiges an Neuerungen, wo ich zunächst skeptisch war, ist von der Python-Community im Endeffekt ganz gut angenommen worden. Und wenn man sich so die Beliebtheitswerte unter den Programmiersprachen anguckt, dann scheinen die Python-Entwickler alles richtig zu machen. :)

Hier ist übrigens der besagte Beitrag:
viewtopic.php?p=424565#p424565

War wohl erst vor einigen Tagen und nicht Wochen. Keine Ahnung, warum mir das schon so lange her vorkam.
Benutzeravatar
Dennis89
User
Beiträge: 1037
Registriert: Freitag 11. Dezember 2020, 15:13

Vielen Dank für eure Antworten.

Ich bin da auch nur zufällig drauf gestoßen und habe mich dann gewundert ob das vielleicht in manchen Bereichen eine "Na endlich, darauf haben wir schon lange gewartet"-Neuerung ist oder ob das eher mal genutzt wird, weil es jetzt da ist.

War ja klar, diesen Beitrag habe ich natürlich übersehen :D

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 12737
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: ``match``/``case`` ist halt noch relativ neu und beruflich habe ich nicht immer und überall das neueste Python zur Verfügung, darum bin ich mit so etwas eher konservativ. `pairwise()` kommt bei mir auch immer noch aus `more_itertools`. 🙂

Im PEP ist glaube ich auch ein schönes Beispiel mit dem `ast`-Modul. Mir geht es so ähnlich wie noisefloor, das ich in bestehenden Programmen wenig Anwendungsfälle finde. Am ehesten wo mit APIs und JSON gearbeitet wird, wo man die Strukuren matchen kann um an Einzelwerte zu kommen. Aber auch nur wenn das wenige Werte sind, die man an einen Namen binden möchte. Für das matchen, validieren, umbauen von umfangreicheren JSON-Datenstrukturen verwende ich `glom`.

Ich hatte auch mal gezielt meine Advent of Code Programme abgeklopft um zu schauen ob ich da was mit ``match``/``case`` machen kann, hatte aber nichts gefunden was nicht deutlich umgeschrieben werden musste. Im Grunde ist das was für algebraische Datentypen, also man muss da von Anfang an ein bisschen mehr mit funktionaler Programmierung im Kopf herangehen und ein bisschen weniger objektorientiert, wo man diese Fälle eher versucht in den Datentypen als Verhalten zu modellieren statt das irgendwo an einer Stelle für verschiedene Typen als Patternmatching zu machen, was ein bisschen schlechter wartbar/erweiterbar ist.

Das ist interessant wenn man Verhalten von bestehenden Datentypen abhängig machen will, beispielsweise wenn man einen AST aus Objekten von bestimmten Typen hat, aber weniger wenn man die Datentypen selbst implementieren kann.
I haven't lost my mind!
I've got it on tape somewhere…
Benutzeravatar
snafu
User
Beiträge: 6681
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Man sollte der Sache auf jeden Fall eine Chance geben und abwarten, wohin der Weg geht. f-Strings fand ich am Anfang auch total "strange", weil da magisch etwas mit dem umgebenden Namensraum gemacht wird, ohne dass man die genutzten Argumente dafür übergeben muss. Aber inzwischen möchte ich dieses Konzept nicht mehr missen.

Ich mag es jedenfalls sehr, dass Python immer wieder neue Dinge ausprobiert und auch bereit ist, "alte Zöpfe" abzuschneiden.
Benutzeravatar
DeaD_EyE
User
Beiträge: 980
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Vorhin hatte ich beim Baden noch über das Structural Pattern Matching nachgedacht und bin im Kopf die Anwendungsfälle durchgegangen.

Mir sind nicht viele bekannt. Jedes Mal, wenn ich es verwendet habe, fiel auf, dass ohne Pattern Matching der Code kürzer war und weniger eingerückt.

Hier mal ein Anti-Beispiel:

Code: Alles auswählen

import datetime


def is_feb(dt):
    match dt:
        case datetime.datetime(month=2):
            return True
            
    return False


dt = datetime.datetime(2022, 2, 1)
print(is_feb(dt))

# wieso nicht gleich so
print(dt.month == 2)
Vielleicht finde ich mal irgendwann einen guten Anwendungsfall.
Die Verarbeitung von JSON aus einer Rest-API wäre vielleicht ein Anwendungsfall für Strucural Pattern Matching.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
__blackjack__
User
Beiträge: 12737
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wir können ja alle mal beim nahenden Advent of Code im Hinterkopf haben, dass es dieses Konstrukt gibt, und schauen ob man es bei der Lösung verwenden kann. 🤓
I haven't lost my mind!
I've got it on tape somewhere…
Benutzeravatar
Dennis89
User
Beiträge: 1037
Registriert: Freitag 11. Dezember 2020, 15:13

Danke für die weiteren Antworten.

Ja richtig, du (blackjack) hattest ja mal was geschrieben, dass du beruflich immer mit älteren Versionen arbeitest. Ich frage dich in 5 Jahren noch einmal :D

Dann bin ich mal auf eure Lösungen gespannt 🙂

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 12737
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@snafu: Ich finde das übrigens nicht so gut das Python auch mal Sachen ausprobiert. Das gab es früher *explizit* *nicht*. Da musste für eine Änderung an der Python-Syntax ein *guter* Grund und Anwendungsfall vorliegen, der *richtig* Vorteile bringt und nicht nur vielleicht, weil's so etwas in einer anderen Programmiersprache gibt.

Die Sprache ist an sich ja schon nicht einfach, auch wenn das gerne mal behauptet wird, und mit jedem Sprachfeature wird sie komplexer. Bei ``match``/``case`` jetzt mit ”Soft-Schlüsselworten”, denn die beiden kann man ja trotzdem noch als Variablennamen verwenden. Und was dabei auch verloren gegangen ist, ist ein einfacher Parser der bei jedem Token wusste was da für ein Sprachkonstrukt folgen muss, statt das man erst mal mehrere Token in die Zukunft schauen muss um zu wissen *was* man da eigentlich gerade für ein Konstrukt hat.

Und es ist nicht nur die Syntax, sondern auch, wie man hier sieht, ein weiterer Weg die gleichen Probleme zu lösen und damit eine zusätzliche Entscheidung.
I haven't lost my mind!
I've got it on tape somewhere…
narpfel
User
Beiträge: 619
Registriert: Freitag 20. Oktober 2017, 16:10

Ich habe `match` ein paar mal bei AoC benutzt, insbesondere wenn sich für das Problem angeboten hat, in sum types zu denken. Als Beispiel:

Code: Alles auswählen

def compare(left, right):
    match (left, right):
        case int(), int():
            return left - right
        case int(), list():
            return compare([left], right)
        case list(), int():
            return compare(left, [right])
        case list(), list():
            for x, y in zip(left, right):
                result = compare(x, y)
                if result != 0:
                    return result
            return compare(len(left), len(right))
für 2022 Tag 13. Problem war, dass man eine verschachtelte Liste auf eine komische Weise vergleichen sollte und die Elemente der Liste konnten entweder `int`s sein oder wieder Listen.
__blackjack__ hat geschrieben: Montag 20. November 2023, 22:11 Ich finde das übrigens nicht so gut das Python auch mal Sachen ausprobiert. Das gab es früher *explizit* *nicht*. Da musste für eine Änderung an der Python-Syntax ein *guter* Grund und Anwendungsfall vorliegen, der *richtig* Vorteile bringt und nicht nur vielleicht, weil's so etwas in einer anderen Programmiersprache gibt.
Finde ich auch. Beispiele sind hier der Walross (ist Python jetzt eine Codegolf-Sprache?) und `match`, was IMHO erst dann richtig Sinn macht, wenn man einen Type Checker hat, der prüft, ob man alle Möglichkeiten abgedeckt hat. Das geht mit `mypy` zwar, aber da schreibt man sich so viel extra Code, dass es (für mich) fragwürdig ist, ob sich das als tradeoff lohnt.
Benutzeravatar
Dennis89
User
Beiträge: 1037
Registriert: Freitag 11. Dezember 2020, 15:13

Tag 13, in den Genuss bin ich noch nicht gekommen. Danke für dein Beispiel.
Das hätte ich spontan vermutlich mit 'if' gelöst und wesentlich mehr schreiben müssen.


Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
snafu
User
Beiträge: 6681
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Also den Walrus-Operator finde ich in manchen Situationen ganz gut. Und zwar dann, wenn man einen Rückgabewert testet und im positiven Fall diesen Wert direkt weiterverwendet. Ein typisches Beispiel:

Code: Alles auswählen

if (m := re.match(...)):
    do_something(m.groups())
Benutzeravatar
__blackjack__
User
Beiträge: 12737
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ohne den Operator:

Code: Alles auswählen

m = re.match(...)
if m:
    do_something(m.groups())
Ich weiss nicht ob das wirklich extra Syntax wert ist. Und vor allem nicht den ganzen Ärger inklusive das hinschmeissen von Guido als BDFL hätte man sich echt sparen können.
I haven't lost my mind!
I've got it on tape somewhere…
narpfel
User
Beiträge: 619
Registriert: Freitag 20. Oktober 2017, 16:10

__blackjack__ hat geschrieben: Dienstag 21. November 2023, 20:37 Ich weiss nicht ob das wirklich extra Syntax wert ist.
Insbesondere wenn man bedenkt, dass `:=` Namen aus Comprehensions leakt:

Code: Alles auswählen

In [1]: [x := 42 for _ in range(10)]
Out[1]: [42, 42, 42, 42, 42, 42, 42, 42, 42, 42]

In [2]: x
Out[2]: 42

In [3]: del x

In [4]: [x for x in range(10)]
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [5]: x
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 1
----> 1 x

NameError: name 'x' is not defined
Und dass, nachdem man das Verhalten von anderen in Comprehensions eingeführten Namen extra für Python 3 repariert hat.

Und ob das wirklich gut lesbar ist, Seiteneffekte in `if`-Conditions oder anderswo tief in irgendeiner Expression versteckt zu haben... Ich bin nicht überzeugt.
Antworten