Ten pattern matching na třídu bude občas docela peklo, protoze vubec nebere ohled na argumenty metody __init__, jak by se na prvni pohled zdalo.
Specifikace je tady: https://peps.python.org/pep-0634/#class-patterns
class Foo:
def __init__(self, x, y=0, z=0):
self.a = x
self.b = y
self.c = z
match subject:
case Foo() - matchuje pomoci isinstance(x, Foo)
case Foo(a=1, b=2) - navic testuje zda subject.a == 1 a subject.b==2
case Foo(1, a=1, b=2) - Nejprve se zase provede isinstance(x, Foo), pak se pomoci subject.__match_args__ se zjisti jmeno atriburtu pro prvni argument a pak se zkontrolujou hodnoty atributu stejne jako v prechozim pripade. Pro built-in typy (viz vycet v dokumentaci) se to samozrejme chova jinak.
To ale znamena, ze vyraz Foo(x, y=z) uvnitr 'case' znamena (semanticky) neco uplne jineho, nez ve zbytku kodu. Nejsem si jisty, jestli se mi to libi.
Vnorene typy funguji, pokud myslite tohle
class Point: def __init__(self, x, y): self.x = x self.y = y class Line: def __init__(self, a, b): self.a = a self.b = b l = Line(Point(0, 0), Point(1, 1)) match l: case Line(a=Point(x=0, y=0), b=Point(x=x, y=y)): print(x, y) case _: print('no match')
vypise 1, 1
Na to je jednoduché řešení; nepoužívat positional patterns vůbec. Já ve skutečnosti v Pythonu preferuju používat keyword argumenty v Pythonu; pak je rozumná jistota, že posílám hodnoty tam, kam potřebuju a žádná změna signatury funkce/metody to nerozbije. Explicitní je lepší než implicitní a tady na 100%.
> On asi neni problem jen v signature, ten konstruktor muze argumenty ruzne transformovat.
Nejen konstruktor, objekt v Pythonu je obecně mutable a s atributy se může stát kdykoli cokoli. Já jsem, co se týče signatury, ale měl na mysli normální volání funkcí, ne pattern matching.
31. 8. 2022, 19:24 editováno autorem komentáře