Search code examples
pythonpattern-matchingliterals

Python pattern match on an operator


I'm trying to build a function that would match on a operator , like - :

def testM(x):
    match x:
        case (operator.sub,a,b):
            return operator.sub(a,b)
        case ('-',a, b):
            return a-b
        case ("+",a,b):
            return a+b
        case ("other strange op",a,b,c):
            return (a+b-c)
        .......
        case _ : 
            return 0

The function will be used in jupyter, so user will type it quite frequently. I would like to make it minimal keystroke possible

testM('-',5,1)  ## 3 key strokes
# it works and return 4 

testM((operator.sub,4,1))   ## 12 key strokes
# it works and return 3

The goal is , user can call it like, but it doesn't work.

testM(-,5,1)  ## only 1 key strokes
# it return 4 

Is there a way to escape evaluation of - in the parameter ? then python won't raise error ?


Solution

  • I'm not sure pattern matching is the way to go here. You could just check the type of your operator and return the desired operation. An example checking for callable and string:

    from simpleeval import simple_eval
    from functools import reduce
    
    def testM(*x):
        if callable(x[0]):
            return reduce(x[0], x[1:])
        elif isinstance(x[0], str):
            return simple_eval(x[0].join(map(str, x[1:])))
        #else: handle further situations if needed
    

    Output:

    print(testM('-', 5, 2))                #3
    print(testM('+', 5, 2, 4))             #11
    print(testM(operator.add, 5, 2, 4))    #11
    

    Edit: using match...case, it would look like this:

    def testM(*args):
        match args:
            case [x, *p] if callable(x):
                return reduce(x, p)
            case [x, *p] if isinstance(x, str):
                return simple_eval(x.join(map(str, p)))
            #handle further cases if needed