Artem Ilin
Artem Ilin

Reputation: 375

SyntaxError when using python pattern matching with condition and a wildcard

I want to use pattern matching to pass through two variables and I need to use conditions with both of them in different cases.

match '12345', '23456':
    case _, b if '456' in b:
        print('True')
    case a if '123' in a, _:
        print('True')
    case _:
        print('False')

I got SyntaxError: invalid syntax on that second case. The first one seems to be working though. It seems like one cannot use wildcard _ after condition. I know I could use two match/case constructions or classical if/elif/else, but I would prefer single match/case construction to work.

Python version - 3.10.6

Upvotes: 0

Views: 333

Answers (2)

chepner
chepner

Reputation: 531165

See https://docs.python.org/3/reference/grammar.html.

The guard in a match statement is defined by this rule:

guard: 'if' named_expression 

which is to say, the keyword if followed by a named_expression. '123' in a, _ is not a named_expression, though. Why not? In short, because it contains a comma.

named_expression:
    | assignment_expression
    | expression !':='

expression:
    | disjunction 'if' disjunction 'else' expression 
    | disjunction
    | lambdef

You can follow disjunction, etc, to see the full definition of expression (the myriad rules are how precedence is encoded in the grammar). The comma, however, is part of an expressions value, which is intuitively a comma-separated sequence of expressions.

expressions:
    | expression (',' expression )+ [','] 
    | expression ',' 
    | expression

Semantically, it wouldn't make sense anyway. Even if you parenthesized it to read

case a if '123' in (a, _):
    print('True')

what's the value of _? That's a tuple display, not a pattern, so (a, _) has to evaluate to some value in order to evaluate '123' in (a, _). The pattern is a, on the other side of the if, which has been matched against the tuple.

Upvotes: 0

quamrana
quamrana

Reputation: 39354

I think you've simply got the wrong idea about how the syntax works.

(disclaimer: I've never used this new feature of python 3)

I think you should have the pattern to the left and the if on the right:

match '12345', '23456':
    case _, b if '456' in b:
        print('True')
    case a,_ if '123' in a:
        print('True')
    case _:
        print('False')

Upvotes: 1

Related Questions