7

I tried to replace an if/elif/elif/.../else code block with the shorter match/case from Python 3.10. I have three constants defined and want to do something different for each one, so my code looks roughly like this:

>>> const_a = 1
>>> const_b = 2
>>> const_c = 3
>>> interface = const_b  # example
>>> match interface:
...     case const_a:
...             print("case a")
...     case const_b:
...             print("case b")
...     case const_c:
...             print("case c")

However, when running this code, there will be an Exception:

File "<stdin>", line 2
SyntaxError: name capture 'const_a' makes remaining patterns unreachable

What am I doing wrong?

mara004
  • 1,435
  • 11
  • 24

1 Answers1

4

The match...case is more than just a switch...case. From https://www.python.org/dev/peps/pep-0622/#patterns:

  • A capture pattern looks like x and is equivalent to an identical assignment target: it always matches and binds the variable with the given (simple) name.
  • A constant value pattern works like the literal but for certain named constants. Note that it must be a qualified (dotted) name, given the possible ambiguity with a capture pattern. It looks like Color.RED and only matches values equal to the corresponding value. It never binds.

So you're going to have to create an object that has those variables as attributes and use the qualified names in the match

import types

consts = types.SimpleNamespace()
consts.A = 1
consts.B = 2
consts.C = 3

interface = 2

match interface:
    case consts.A:
        print("A")
    case consts.B:
        print("B")
    case consts.C:
        print("C")

Which, as expected, prints B

For more information on why, see https://www.python.org/dev/peps/pep-0622/#alternatives-for-constant-value-pattern

Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
  • Thanks! I think it is also possible to use an Enum then, right? However, I dislike the design descision to only allow "qualified" names and not conventional constants. – mara004 Apr 20 '21 at 15:36
  • 1
    conventional constants are disallowed for a reason: that way causes ambiguity with the _capture_ match pattern. – Pranav Hosangadi Apr 20 '21 at 15:38
  • 1
    @mara004 it's possible something similar was [proposed and rejected](https://www.python.org/dev/peps/pep-0622/#id16) or [deferred](https://www.python.org/dev/peps/pep-0622/#id19) – Pranav Hosangadi Apr 20 '21 at 19:25
  • 12
    People have been asking for something like a switch case for 30 years. Now it finally gets implemented and you cant even match a number with constants without a workaround like this. Who cares about all the advanced pattern matching you can do with this if it fails for such a common and simple use case without a workaround like this? This honestly just blows my mind. – Eric Nov 24 '21 at 12:41
  • Rule 1: Simple is best. Rule 2: When simple isn’t possible, it’s not best. – Dave McNulla Dec 08 '22 at 19:21