Невозможно изменить глобальные переменные в функции с помощью инструкции exec()?
Почему я не могу изменять глобальные переменные внутри функции, используя exec()? Он отлично работает, когда оператор присваивания находится вне exec(). Вот пример моей проблемы:
>>> myvar = 'test'
>>> def myfunc():
... global myvar
... exec('myvar = "changed!"')
... print(myvar)
...
>>> myfunc()
test
>>> print(myvar)
test
Ответы
Ответ 1
Per документы, оператор exec
принимает два необязательных выражения, по умолчанию - globals()
и locals()
, и всегда выполняет изменения (если есть) в locals()
.
Итак, просто будьте более явным/конкретным/точным...:
>>> def myfunc():
... exec('myvar="boooh!"', globals())
...
>>> myfunc()
>>> myvar
'boooh!'
... и вы сможете использовать глобальные переменные для вашего сердечного содержимого.
Ответ 2
Чтобы добавить к ответу Alex: хотя, если вы опускаете аргументы locals/globals, которые они по умолчанию используют для локалей и глобальных символов вызывающего, это только удобный хак; это не означает, что они наследуют полный контекст выполнения вызывающего. В частности:
а. вложенные ячейки области недоступны исполняемому коду. Так что это не удается:
def f():
foo= 1
def g():
exec('print foo')
g()
f()
б. global
объявления не переносятся в исполняемый код. Таким образом, по умолчанию, как и в вашем примере, записанные переменные помещаются в словарь locals. Однако вы можете заставить его работать, говоря
exec('global myvar\nmyvar = "changed!"')
Вы действительно не хотите делать это, если сможете это сделать. global
уже не приятно, а exec
- это скорее запах кода сам по себе! Вы бы не хотели их комбинировать, если не было никакой альтернативы.
Ответ 3
Как насчет этого:
>>> myvar = 'test'
>>> def myfunc():
... exec('globals()["myvar"] = "changed!"')
... print(myvar)
...
>>> myfunc()
changed!
>>> print(myvar)
changed!
Он работал у меня в Python 2.6.
EDIT: На самом деле объяснение Алексея Мартелли намного лучше, чем мое:)