Is there a way to match inequalities in Python ≥ 3.10?
Asked Answered
O

3

44

The new structural pattern matching feature in Python 3.10 is a very welcome feature. Is there a way to match inequalities using this statement? Prototype example:

match a:
    case < 42:
        print('Less')
    case == 42:
        print('The answer')
    case > 42:
        print('Greater')
Opulence answered 25/10, 2021 at 14:57 Comment(1)
Personally I would use a simple if elif else statement when matching (in)equalities and not structural patterns.Shaynashayne
N
61

You can use guards:

match a:
    case _ if a < 42:
        print('Less')
    case _ if a == 42:
        print('The answer')
    case _ if a > 42:
        print('Greater')

Another option, without guards, using pure pattern matching:

match [a < 42, a == 42]:
    case [True, False]:
        print('Less')
    case [_, True]:
        print('The answer')
    case [False, False]:
        print('Greater')
Nalley answered 25/10, 2021 at 15:2 Comment(6)
In the first example I'd rather just use the old if/elif which is much easier to read IMO.Holm
For the first case it seems that case [True, _]: also works and is consistent with the pattern in your second case. Or you could make the second one case [False, True]: if you wanted to make the consistency the other way.Liegeman
What's the point of the first one if it's basically just an if-elif with more steps?Chute
@Chute match-case seems terribly designed :/ Should have allowed match a: case < 42Manhandle
@Manhandle Well, TBF, this isn't what it's built for. It's very much structural pattern matching. Take a look at this answer I wrote and how much cleaner match-case makes the parsing code.Chute
Now that I think about it, the second one is also just an if-elif with more steps: if a < 42: ... elif a == 42: ... else: ..., since, as @Dennis said, "case [True, _]: also works".Chute
C
8

In this example, it's simpler to use good ol' if-elif, even if it means repeating the variable name.

if a < 42:
    print('Less')
elif a == 42:
    print('The answer')
elif a > 42:
    print('Greater')

P.S. Using an enum and comparison function like in Thomas Sollie's answer is good for adding more structure to your program, but it seems like overkill for basic scripts and such.

Speaking of code style, avoid magic numbers: If all three 42's in your code represent the same thing, give it a name, for example:

the_answer = 42
if a < the_answer:
...
Chute answered 22/1, 2023 at 19:35 Comment(0)
V
7

A match-case statement inherently is designed for matching equalities (hence the word "match"). In your prototype example you could achieve this by matching with an if clause (as proposed by other answers), however now you are in essence simply matching True and False, which seems redundant.

One way other languages solve this is via comparisons using Enums:

from enum import Enum


class Ordering(Enum):
    LESS = 1
    EQUAL = 2
    GREATER = 3


def compare(a, b):
    if a < b:
        return Ordering.LESS
    elif a == b:
        return Ordering.EQUAL
    elif a > b:
        return Ordering.GREATER


match compare(a, 42):
    case Ordering.LESS:
        print("Less")
    case Ordering.EQUAL:
        print("The answer")
    case Ordering.GREATER:
        print("Greater")
Vale answered 12/10, 2022 at 12:58 Comment(3)
Off-topic, but that enum is incomplete for other numeric types. If the numbers could be floats, they could be NaN, which never compares less, equal, or greater, only not equal. And, hypothetically, you could have a third-party type that doesn't compare less, equal, greater, or not equal. So I might add a NOT_ORDERABLE member for that or have compare() throw a TypeError.Chute
At that point I have a hard time justifying the use of a case statement when you can simply use the if/elif. It's half the lines and easier to read.Patrology
@MarcelWilson case statements are definitely not for simple comparisons. If you are using an enum like this example, it can be super useful: match value: case CustomType.ThisThing: thisThingFunction(), case CustomType.ThisOtherThing: thisOtherFunction() - with only a few things its pretty much just a more complicated if else - with dozens of different options its cleaner and i believe fasterChromoplast

© 2022 - 2024 — McMap. All rights reserved.