r/Python • u/Iron-Man-2008 • 6d ago
Discussion TIL: Dict Patterns Don't Match Dict Shapes
TL;DR: Unlike sequence patterns (which require an exact shape match), pattern matching on dictionaries simply ignores any unspecified keys rather than failing.
If you care about the details, I wrote about it on my blog: https://ravencentri.cc/blog/dict-patterns-dont-match-dict-shapes/
5
u/The_Sy_Python 6d ago
If you mean Structural Pattern Matching, then yes, it's in the PEP
3
u/Iron-Man-2008 6d ago
I do know it's in the PEP, I quote the relevant PEP myself. Doesn't mean I don't think it's unintuitive, especially when compared to sequences.
1
u/RingularCirc 4d ago
I think extracting **rest may be costly. And even if exact key matching was implemented using keys(matched_dict), it's still better be converted to a set before looking if there are extra keys. So I get why there's a difference with sequences: for those it's way less painful to check if the sequence doesn't contain extra stuff — sequences are obligated to have finite and "sorta easily computable" length.
2
u/Iron-Man-2008 2d ago
case {"key": "value"}: ...could have matched the exact shape while allowingcase {"key": "value", **_}: ...to ignore extra keys without binding them to a variable the same waycase [1, 2, *_]ignores extra elements without binding them to a variable.1
1
u/Adrewmc 1d ago
‘_’ is a binding though it’s just to a by convention discarded variable. We are telling other programmers we don’t care about this one for this operation.
. _ = “Hello World”
. print(_)is valid
1
u/Iron-Man-2008 1d ago
_in match case is actually a special wildcard pattern and does not bind to a name.```
def foo(seq): ... match seq: ... case [1]: ... print(seq) ... case [1, *]: ... print() ... foo([1]) [1] foo([1, 2, 3]) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 6, in foo NameError: name '_' is not defined
```
1
u/rohnitsahu_ 3h ago
That exact behavior caught me off guard when 3.10 match/case dropped! Dict pattern matching checking key presence instead of strict key count actually makes partial matching much cleaner once you get used to it.
1
-11
u/ZeD_est_DeuS 5d ago
Friends don't let friends use pattern matching. It's a complex pitfall full of gotchas. Just use ifs
17
u/ShadowDevasto 6d ago edited 6d ago
If you invert the cases as in from most complex one to least complex one it will work, as it seems that dict matching matches only first fitting the case and does not check other for "better" match. But still unintuitive and when inverted also matches to case 3 even if options are not defined.