8

I've been playing around with Structural Pattern Matching in Python 3.10 and can't figure out how to get it to match a set. For example I've tried:

a = {1,2,3}

match a:
    case set(1,2,3):
        print('matched')

and I've tried:

a = {1,2,3}

match a:
    case set([1,2,3]):
        print('matched')

As well as:

a = {1,2,3}

match a:
    case [1,2,3] if isinstance(a, set):
        print('matched')

I'm guessing there is a way to do this since we can match other objects and I'm just missing the correct syntax but I can't think of what else to try. Any help would be appreciated! Thanks!

7
  • I don't think it makes sense to use SPM for sets. If you write case {a, b, c}: how would it know which variable should get each value in the set, since sets don't have any order? Commented Jun 3, 2021 at 20:15
  • I can see why someone would make that decision for sure. I might suggest in a case where multiple types are potentially returned it would be nice to use the same match statement rather than combining a match statement and an if-block but I get the argument that you shouldn't have those cases in proper code. I'm also seeing that I can't match dictionaries where tuples or frozensets are keys as well. I was thinking PEP-634 indicated that all of these basic types were supported. Maybe I'm just misunderstanding what it's saying? Commented Jun 3, 2021 at 20:26
  • I'm also seeing that I can't match dictionaries where tuples or frozensets are keys as well. It seems like it would be helpful to be able to match dicts with tuples or frozensets as keys but perhaps that too is going beyond what SPM is meant for Commented Jun 3, 2021 at 20:28
  • You seem to be trying to use this as switch/case. That's not the intended use. Commented Jun 3, 2021 at 20:28
  • 2
    I for sure am :) I guess my understanding was this was meant to be switch / case + pattern matching goodness all rolled into one. Perhaps I'm viewing it wrong altogether? It seems I can match specific strings in lists or dict keys as well as specific values of numbers, etc... and even matching equality between custom classes works. I'm surprised the tutorial shows matching custom classes with specific values if we can't match built-in types with specific values Commented Jun 3, 2021 at 20:32

2 Answers 2

8

This isn't really how structural pattern matching is meant to be used; the pattern you're matching is more about value than structure. Because of this, I think you'll find that the equivalent if form is much more readable:

if a == {1, 2, 3}:
    print('matched')

With that said...

Python 3.10 doesn't have syntactic support for matching sets; it only has dedicated "display" syntax for sequences and mappings. I think we briefly considered this, but ultimately dropped it because wasn't very useful or intuitive (and it's easy enough to add in a later version).

Fortunately, it's possible to match any value by equality using a qualified (or "dotted") name. If you need to match a set as part of a larger pattern or match block, that's probably the best way to do it:

class Constants:
    SET_123 = {1, 2, 3}

match a:
    case Constants.SET_123:
        print('matched')

It can also be combined with a class pattern if you only want to match sets (and not, for example, frozensets):

match a:
    case set(Constants.SET_123):
        print('matched')
Sign up to request clarification or add additional context in comments.

Comments

5

Since the match construct doesn't use set equality to compare sets, you will need to use a guard to do it explicitly:

a = {1,2,3}

match a:
    case _ if a == set([1,2,3]): 
        print('matched')

It's unintutive that sets aren't compared with set equality by default.

1 Comment

why not case set() if a == {1,2,3}?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.