Is there a way to avoid writing case again and again?

from,

for x in [1, 1.2, 'abc']:
  match x:
    case int(): print(f'int {x}')
    case float(): print(f'float {x}')
    case str(): print(f'string {x}')

to,

for x in [1, 1.2, 'abc']:
  match x:
    int(): print(f'int {x}')
    float(): print(f'float {x}')
    str(): print(f'string {x}')

using for loops or exec or some other way to do this
also I would like to use ; here, I think so, it is currently not valid for case statements, that is,

for x in [1, 1.2, 'abc']:
  match x:
    int(): print(f'int {x}'); float(): print(f'float {x}'); str(): print(f'string {x}')

or

for x in [1, 1.2, 'abc']:
  match x: int(): print(f'int {x}'); float(): print(f'float {x}'); str(): print(f'string {x}')

but here, multiple use of : appears to be less readable.
or

[match x: int(): print(f'int {x}'); float(): print(f'float {x}'); str(): print(f'string {x}') for x in [1, 1.2, 'abc']]

in case the body of case is bigger then I would like to create function/s.

[(match x: int(): func1(x); float(): func2(x); str(): func3(x);) for x in [1, 1.2, 'abc']]

What’s wrong with having to write “case”? It’s just part of the pattern matching syntax.

1 Like

No.

Using match…case for your code is massive overkill. What you can do is:

for x in [1, 1.2, 'abc']:
    print(type(x).__name__, x)

instead.

1 Like

the only reason for me to not like writing case again and again is that it is the only option available, there is no choice.
after every match, the only thing that is valid is case.
if there were multiple options after match, let us say like finally or something.
and then had to make a choice between case or finally or other options, then there would be no issue with writing case again and again.
but here, the only option is writing case.
I understand that it is made to work in a similar way to switch-case statement, but I wish there was a way to avoid writing case again and again.

my first post is just one example, the body of case statement could be different than the one I described.

I don’t really understand what you mean when you say “it is the only option available”. Your match has 3 options available. I also don’t understand what you mean by “after every match, the only thing that is valid is case”.

Again, writing “case” is just how you denote the patterns you’re trying to match the value against.

Also, in your first post, you mentioned using exec. I’d really caution against solutions that use exec - they lead to code that’s difficult to read and maintain. Most of the time there are better ways to do things.

I mean no other keyword is valid after match
for example,

match x:
  for ...

or

match x:
  funciton_call()

or

match x:
  try:
    ...
  except:
    ...

or

match x:
  class A:
    pass

none of it is valid, the only keyword that is valid is case, there is no other option.

By ND via Discussions on Python.org at 29Apr2022 04:20:

I don’t really understand what you mean when you say “it is the only
option available”. Your match has 3 options available. I also don’t
understand what you mean by “after every match, the only thing that is
valid is case”.

Again, writing “case” is just how you denote the patterns you’re trying
to match the value against.

I think the OP is asserting that the word “case” is mandatory and
therefore redundant. Haven’t checked if it is truly redundant mysef.

Cheers,
Cameron Simpson cs@cskk.id.au

Sure, they could have omitted “case”, but it’s not that big a deal. Neither Rust nor ML make you write “case” in their pattern matching.

I write Scala at work and in that language, you do have to write “case”. At least with algebraic data types (which I don’t think you can do in Python), since there’s a finite set of possibilities, the IDEs can generate the whole match expression for you. In the stuff I write, there tend not to be many possibilities, though (option types with two possibilities, or result types again with two possibilities are the most common).

I’m a bit confused. @vainaixr Can you explain how you would interpret these alternatives? For instance, in your last example (match x ... class A ...), what value is matched against x that would tell the interpreter to execute the class statement?

The match statement implements a pattern matching cascade identified by the various case expressions. You need something that ties the value of x to a particular indented block to execute.

If you haven’t read PEP 622, I think that would be a good place to begin.

the class A one is just an example that is invalid, I do not expect it to work, that is just to list the keywords that do not work after specifying match.
all four examples, for, function_call(). try-except, class are invalid, I do not expect them to work.

Reference:
Structural Pattern Matching

In my opinion, from a beginner’s perspective case help to differentiate between each pattern that wants to be checked against value of match. Also OP example I think to simple to use match ... case, and if more complex example it’s exist case clause help readability.

1 Like

I prefer:

cases = {
    int: lambda x: print(f'int {x}'),
    float: lambda x: print(f'float {x}'),
    str: lambda x: print(f'string {x}')
}

for x in [1, 1.2, 'abc']:
    cases.get(type(x))(x)  # first gets; second calls.

I think people are missing the structural part of the match statement’s structural pattern matching. Sure, if you know you will have a precise small set of inputs, you won’t really need it. The simple example with int/float/str doesn’t really expose its power. I suggest people read PEP 636, Structural Pattern Matching: Tutorial (@gunungpw already posted it but I want to emphasize it) which demonstrates the flexibility of the match statement in the design of command language for a simple text adventure game. Using match/case provides for a much more straightforward implementation of that interface.