Как использовать функцию eval () со списком переменных? - PullRequest
0 голосов
/ 28 января 2019

У меня есть список функций в виде строк:

["y + x + 3", "x**2 + y**2 - 17"]  # 2 functions in list

У меня есть список Sympy Symbol объектов (в основном, переменных), чей атрибут .name соответствует именам переменных в строках функций:

[Symbol(x), Symbol(y)]
# list element 0's .name attribute is "x" 

Я обнаружил, что в Python есть аккуратная функция с именем eval(), которая может оценивать строки, например:

x = 1
eval("x + 3") # Result should be 4

По сути, это то, что я хочу делать со строками своих функций.Однако, поскольку это динамическая реализация, у меня в моей программе нет переменных, определенных в строке выше eval(), они вместо этого находятся в списке.Например, в приведенном выше примере x определен как 1, поэтому функция eval() может использовать его.

Но у меня есть переменные в списке, которые не определены как переменные в области действия моей функции. Как я могу использовать функцию eval() и использовать свой список переменных?

Ответы [ 5 ]

0 голосов
/ 28 января 2019

Вы могли бы сделать что-то вроде этого:

import math

symbols = {'sqrt': math.sqrt, 'x': 5, 'y': 6}

func_strings = ["y + x + 3", "x**2 + y**2 - 17", "sqrt(1764)"]

for expression in func_strings:
    result = eval(expression, {'__builtins__': None}, symbols)
    print('{} -> {}'.format(expression, result))

Вывод:

y + x + 3 -> 14
x**2 + y**2 - 17 -> 44
sqrt(1764) -> 42.0
0 голосов
/ 28 января 2019

Посмотрите на полное определение eval (expression[, globals[, locals]])

Вы можете заменить globals / locals на eval.

Например

eval("x + 3", {"x":1}) # Result should be 4

Как я могу использовать функцию eval () и использовать мой список переменных?

У вас есть 2 пространства имен, и вы можете делать с ними все, что хотите.

0 голосов
/ 28 января 2019

eval принимает локальные переменные в качестве третьего аргумента ( ссылка ), поэтому вы можете сделать это:

from sympy import Symbol
zs = [Symbol('x'), Symbol('y')]
eval('x+y', None, dict([z.name, z] for z in zs))

Однако, возможно, вам следует использовать parse_expr который является частью SymPy.

from sympy import Symbol
from sympy.parsing.sympy_parser import parse_expr
zs = [Symbol('x'), Symbol('y')]
parse_expr('x+y', local_dict=dict([z.name, z] for z in zs))
0 голосов
/ 28 января 2019

На мой взгляд, лучший способ сделать это - добавить все переменные в locals.Затем вы можете ссылаться на них по имени в eval.Пример:

symbols = [Symbol(x), Symbol(y)]
locals().update({symbol.name:symbol for symbol in symbols})

eval("x+y") # Should return the value of x+y
0 голосов
/ 28 января 2019

Как насчет этого, и вы можете обернуть следующие коды замены и eval в свой класс символов (через inheriate).

import ast

x = 5
y = 6

function_str = "y + x + 3"
function_str = function_str.replace('x', '{x}')
function_str = function_str.replace('y', '{y}')

print(ast.literal_eval(function_str.format(x=x, y=y)))
# 14

Всегда помните, что использование eval - это "EVAL", потому что вы не должны доверятьстрока передана, listeral_eval безопаснее.

...