0

I need to evaluate a mathematical expression in a string like a * np.exp(b * c) (with a, b and c being constants or variables available elsewhere in my code).

From this answer to a similar question on SO, I adapted the following code to try with a minimal example (not calling variables but actual numbers as arguments in a first step):

import numpy as np
import ast
import operator as op

operators = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
             ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor,
             ast.USub: op.neg}

def eval_expr(expr):
    return eval_(ast.parse(expr, mode='eval').body)

def eval_(node):
    if isinstance(node, ast.Num):
        return node.n
    elif isinstance(node, ast.BinOp):
        return operators[type(node.op)](eval_(node.left), eval_(node.right))
    elif isinstance(node, ast.Constant):
        return node.value
    elif isinstance(node, ast.Call):
        if isinstance(node, ast.Call):
            if isinstance(node.func, ast.Name): # for built-in functions like 'max'
                print('node.func.id: ', node.func.id)
                print('Arguments: ', [eval_(a) for a in node.args])
                print('node.func is ast.Name: Now what can I do to actually run the function?')
            elif isinstance(node.func, ast.Attribute): # for a call to a module etc
                print('node.func.value.id:', node.func.value.id)
                print('Arguments: ',[eval_(a) for a in node.args])
                print('node.func is ast.Attribute: Now what can I do to actually run the function?')
    else:
        raise TypeError(node)

print(eval_expr('3*4'))
# 12

eval_expr('max(3, 4)')
# node.func.id:  max
# Arguments:  [3, 4]
# node.func is ast.Name: Now what can I do to actually run the function?

eval_expr('np.exp(3)')
# node.func.value.id: np
# Arguments:  [3]
# node.func is ast.Attribute: Now what can I do to actually run the function?

I tried to identify the different cases for the function calls (i.e., when calling a base function or a function from an external module/library like numpy), but I don't know how to actually run these functions now.

(In my real case, I think I'd be able to pass actual variables or constants from their names as arguments.)

ztl
  • 2,512
  • 1
  • 26
  • 40

0 Answers0