Можно «присвоить» значение выражению eval, манипулируя его абстрактным синтаксическим деревом (AST). Нет необходимости напрямую изменять строку оценки, и если тип нового значения не слишком сложен (например, числовой или строковый), вы можете жестко закодировать его в AST:
- Скомпилируйте eval-выражение в AST.
- Заменить Загрузить контекст выражения в корневом узле на Store .
- Создайте новый AST с помощью Assign оператора в корневом узле.
- Установить target на узел выражения модифицированного eval AST.
- Установить значение на значение.
- Скомпилируйте новый AST в байтовый код и выполните его.
Пример
import ast
import numpy as np
def eval_assign_num(expression, value, global_dict, local_dict):
expr_ast = ast.parse(expression, 'eval', 'eval')
expr_node = expr_ast.body
expr_node.ctx = ast.Store()
assign_ast = ast.Module(body=[
ast.Assign(
targets=[expr_node],
value=ast.Num(n=value)
)
])
ast.fix_missing_locations(assign_ast)
c = compile(assign_ast, 'assign', 'exec')
exec(c, global_dict, local_dict)
class TestClass:
arr = np.array([1, 2])
x = 6
testClass = TestClass()
arr = np.array([1, 2])
eval_assign_num('arr[0]', 10, globals(), locals())
eval_assign_num('testClass.arr[1]', 20, globals(), locals())
eval_assign_num('testClass.x', 30, globals(), locals())
eval_assign_num('newVarName', 40, globals(), locals())
print('arr', arr)
print('testClass.arr', testClass.arr)
print('testClass.x', testClass.x)
print('newVarName', newVarName)
выход
arr [10 2]
testClass.arr [ 1 20]
testClass.x 30
newVarName 40