How can I build an advanced formula from a dict of functions without using eval()?

Question:

I have two dicts of functions that I want to use to build a larger function. The goal is to be able to substitute different functions in their place based on the dict keys. I know using eval() is not the best way in terms of security and speed, but I cannot come up with another way.

def formula(x):
    p1 = 10
    p2 = 20
    p3 = 30
    p4 = 40
    p5 = 50
    p6 = 60

    basic = {0:'+', 1:'-', 2:'*', 3:'/'}
    advanced = {0:np.exp, 1:np.sin, 2:np.cos, 3:np.tan, 4:np.arcsin}

    f = advanced[0](x basic[1] p1)
    print(f)

I know the syntax is incorrect for f above but the goal is:

f = np.exp(x – p1)

Currently, I have it working by:

f = eval(advanced[0] + '(' + 'x' + basic[1] + 'p1' + ')')
Asked By: Trippingbillies41

||

Answers:

eval() can be a security issue when you’re evaluating input from an user, since in most cases you can’t predict what they’re going to input. But it seems safe to use in this scenario.

Anyway, here’s a solution using lambda functions:

def formula(x):
    p1 = 10
    p2 = 20
    p3 = 30
    p4 = 40
    p5 = 50
    p6 = 60

    basic = {0: lambda a,b: a+b, 1: lambda a,b: a-b, 2: lambda a,b: a*b, 3: lambda a,b: a/b}
    advanced = {0: lambda n: np.exp(n), 1: lambda n: np.sin(n), 2: lambda n: np.cos(n), 3: lambda n: np.tan(n), 4: lambda n: np.arcsin(n)}

    f = advanced[0](basic[1](x, p1))
    print(f)

PS: This is an illustrative example. As noted by @wwii, lambda functions are not necessary for advanced since you are holding functions anyway. So advanced[0](3) will work as np.exp(3).

Note that you can hold functions with dictionary keys, as if they were any other value, e.g.:

advanced = {0:np.exp, 1:np.sin, 2:np.cos, 3:np.tan, 4:np.arcsin}
foo = np.exp

print(np.exp(3))
print(advanced[0](3))
print(foo(3))

20.085536923187668
20.085536923187668
20.085536923187668
Answered By: Ignatius Reilly
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.