#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
orexec
— неправильный путь. Если вы действительно описали свою проблему, мы можем указать вам правильное направление
Ответ №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