pythonpython-3.xlist

Extracting from **kwargs


I am writing a pretty basic calculator for functions (for example f(x)=x+5), and the first step is writing a quick function to calculate the result if we already know all the variables. Source code is:

def calc(function, **kwargs):
if re.fullmatch(r'[0-9a-z+\-*/()]+', function) != None:
    return eval(function)
return None

But I need to add a script that changes the function to add in the values instead of the variables. For example, if I call my calc() as calc('x+5*y', x=2, y=7), it should change the function to simply '2+5*7', so that I could put it into eval().

Does anybody have any ideas on how this would be possible, or what are some alternative methods for this?


Solution

  • In Python the eval function takes two additional parameters beyond the expression parameter, namely locals and globals which populate the variables the expression has access to, so a simple solution is just to pass your kwargs to eval's locals and everything works as expected.

    import re
    
    def calc(function, **kwargs):
        if re.fullmatch(r'[0-9a-z+\-*/()]+', function) != None:
            return eval(function, locals=kwargs)
        return None
    
    print(calc('x+y', x=10, y=20)) # Outputs 30
    

    Obligatory warning on never using eval nor relying on regex as a security measure, but this works perfectly for a small concept as this.

    You can read more about globals and locals in python here: What's the difference between globals(), locals(), and vars()?