присваивать значение переменной с помощью eval способом метапрограммирования

#python #eval #metaprogramming

#python #eval #метапрограммирование

Вопрос:

Я хочу присвоить значение переменной с помощью eval способом метапрограммирования. Моя попытка была показана ниже:

 sample = None
var_name = "sample"
value = 0
eval("{0} = {1}".format(var_name, value))
  

Однако я получил следующую ошибку:

 Traceback (most recent call last):
  File "tmp.py", line 4, in <module>
    eval("{0} = {1}".format(var_name, value))
  File "<string>", line 1
    sample = 0
           ^
SyntaxError: invalid syntax
  

Не могли бы вы объяснить, как я могу это сделать? Я думаю, что функция более низкого уровня, подобная assign(var, val) , может существовать, и это позволило назначить с помощью eval. Но я не смог найти такую функцию.

Комментарии:

1. eval Функция Python вычисляет выражения. Он не выполняет инструкции. Присваивание — это оператор, а не выражение. Это объясняет проблему, с которой вы столкнулись. В общем. внесение глобальных изменений с использованием eval — действительно плохая идея.

2. exec делает то, что вы хотите.

3. Но что бы вы ни пытались сделать, пожалуйста, не делайте этого. Вы создаете огромную дыру в безопасности в своей программе. Чего бы вы на самом деле ни пытались достичь, есть лучшие и более безопасные способы.

4. хм, я модифицирую существующее программное обеспечение, и для сохранения обратной совместимости и добавления моей функции использование метапрограммирования кажется единственным способом…

5. @orematasaburo нет, почти наверняка, использование eval or exec — неправильный путь. Если вы действительно описали свою проблему, мы можем указать вам правильное направление

Ответ №1:

Используйте exec вместо:

 sample = None
var_name = "sample"
value = 0
exec("{0} = {1}".format(var_name, value))
  

eval предназначен для вычисления выражения, а не оператора присваивания

Ответ №2:

exec выполняет ли то, что вы пытаетесь сделать?:

 sample = None
var_name = "sample"
value = 5
exec(f"{var_name} = {value}")

print(sample)
  

вывод: 5

Ответ №3:

Если вы находитесь вне функции, вы можете использовать

 globals()[varname] = value
  

Пример:

 >>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> globals()['a'] = 5
>>> a
5
  

Внутри функции есть locals() , но она может только считываться из таблицы символов и не обновляться, поэтому вы должны использовать eval() , как указывали другие ответы.

Вы также можете обмануть, используя setattr / hasattr / getattr для объекта:

 >>> class Object:
...     pass
... 
>>> obj = Object()
>>> obj.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Object' object has no attribute 'a'
>>> setattr(obj, 'a', 3)
>>> obj.a
3
  

Комментарии:

1. ни eval один, ни exec один не обновит локальную таблицу sybol