Traduza uma string de function matemática para uma function

Eu quero ter uma function que leva em uma seqüência de function, como 'x**2+x' ou 'log(x)' e um número como x e retornar um número. Por exemplo:

 translate(2, "x**2") return 4 translate(10, "x**2") return 100 

Isso é o que eu tentei. No entanto, só posso manipular um dígito para x.

 def translate(x, function): func = function.replace('x', str(x)) res = 0 i = 0 while i in range(len(function)): if func[i] == '*': if func[i+1] == '*': res = res**int(func[i+2]) i+=3 else: res *= int(func[i+1]) i+=2 elif func[i] == '+': res += int(func[i+1]) i+=2 elif func[i] == '-': res -= int(func[i+1]) i+=2 elif func[i] == 'l': res += math.log(int(func[i+3])) i+=4 else: res += int(func[i]) i+=1 return res 

Edit: Eu só preciso de uma function simples que traduza desde que eu não estou passando em function complicada louco.

Edit: parece que há um monte de debates sobre eval () inseguro para usar o que deve ser mencionado antes de alguém usá-lo ver esta discussão: Por que está usando ‘eval’ uma má prática?

Use o método embutido eval() .

 def translate(x, function): return eval(function) result = translate(10, "x**2") print(result) 

Saída: 100

Edit2: outra maneira sem eval

 def translate(s): symbols = ['+', '-', '*', '/'] buff = '' num = [] operations = [] for i, c in enumerate(s): if c in symbols: # check for operators # check for double operators like ** if s[i + 1] in symbols: # ie checking the first '*' in '**' operations.append(2 * c) continue elif s[i - 1] in symbols: # ie checking the second '*' in '**' num.append(float(buff)) buff = '' continue operations.append(c) num.append(float(buff)) buff = '' continue else: buff += c num.append(float(buff)) print('input string:', s) print('numbers:', num) print('operations', operations) # "power calculations" to be done first for i, x in enumerate(operations): if x == '**': num[i] = perform[operations[i]](num[i], num[i + 1]) num.pop(i + 1) operations.pop(i) # multiply/division for i, x in enumerate(operations): if x in ['*', '/']: num[i] = perform[operations[i]](num[i], num[i + 1]) num.pop(i + 1) operations.pop(i) # last addition/subtraction for i, op in enumerate(operations): if op == '-': num[i + 1] = -num[i + 1] return sum(num) # define all operations you need, no need to add + or - perform = {'*': lambda x, y: x * y, '/': lambda x, y: x / y, '**': lambda x, y: x ** y } result = translate('5+3+10**2+210-30/2') print('result =', result) 

Saída:

 input string: 5+3+10**2+210-30/2 numbers: [5.0, 3.0, 10.0, 2.0, 210.0, 30.0, 2.0] operations ['+', '+', '**', '+', '-', '/'] result = 303.0 

Edit3: menor com regex

 import re def translate(s): num = re.findall(r'\d+', s) # '\d' means digits only operations = re.findall(r'\D+', s) # '\D' means anything but digits print('input string:', s) print('numbers:', num) print('operations', operations) # "power calculations" to be done first for i, x in enumerate(operations): if x == '**': num[i] = perform[operations[i]](num[i], num[i + 1]) num.pop(i + 1) operations.pop(i) # multiply/division for i, x in enumerate(operations): if x in ['*', '/']: num[i] = perform[operations[i]](num[i], num[i + 1]) num.pop(i + 1) operations.pop(i) # last addition/subtraction for i, op in enumerate(operations): if op == '-': num[i + 1] = -num[i + 1] return sum(num) # define all operations you need, no need to add + or - perform = {'*': lambda x, y: x * y, '/': lambda x, y: x / y, '**': lambda x, y: x ** y } result = translate('5+3+10**2+210-30/2') print('result =', result)