Порядок присваивания имеет значение неожиданно с «exec expr в globals (), locals ()»

Следующий код в Python 2.X печатает «a: 2», как вы ожидали:

def f(): #a = 1 exec "a = 2" in globals(), locals() for k,v in locals().items(): print k,":",v #a = 3 f() 

Но если вы раскомментируете «a = 1», тогда он печатает «a: 1», как я и не ожидал. Даже более странно, если вы раскомментируете строку «a = 3», то она ничего не печатает, чего я определенно не ожидал (у меня была непонятная ошибка, на которую я догадался).

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

Мне бы хотелось узнать, что здесь интерпретирует интерпретатор Python, а также предложения об обходных решениях.

2 Solutions collect form web for “Порядок присваивания имеет значение неожиданно с «exec expr в globals (), locals ()»”

Старый исполняемый exec Python 2 изменит байт-код для поиска как локального, так и глобального пространств имен.

Когда вы определяете a = 2 в глобальном, это тот, который найден, когда a = 1 комментируется. Когда вы раскомментируете a = 3 , это «найденный», но еще не определенный.

Если вы читаете, как таблицы символов обрабатываются в этой замечательной статье Эли Бендерски , вы можете лучше понять, как обрабатываются локальные переменные.

Вы не должны использовать exec для этого типа кода (я надеюсь, что это не производственный код), и он все равно сломается при переносе вашего кода на Py3k:

Функция exec Python 3 уже не является оператором и, следовательно, не может изменить окружающую среду, в которой она находится.


Вероятно, я должен перейти прямо к делу:

Если вы делаете все это динамическое именование, вы должны использовать словарь:

 def f(): data = {'a': 1} data['a'] = 2 if ...: data['a'] = 3 

из документации по функциям locals :

Примечание . Содержимое этого словаря не должно изменяться; изменения могут не влиять на значения локальных и свободных переменных, используемых интерпретатором.

проверка:

 >>> def f(): a = 1 print(locals()) locals()['a']=2 print(a,locals()) >>> f() {'a': 1} 1 {'a': 1} 

Таким образом, вы просто не можете изменить локальный контекст через функцию locals()

  • Python: как передать аргументы функции __code__ функции?
  • когда использовать DataFrame.eval () в сравнении с pandas.eval () или python eval ()
  • Книга Python - Zelle использует eval (), не так ли?
  • Как правильно интерпретировать одну строку кода python?
  • Почему глобальные скобки не копируются, когда я запускаю eval с аргументом globals?
  • ast.literal_eval для переменных в python?
  • Почему Python eval () отклоняет эту многострочную строку и как я могу ее исправить?
  • В чем разница между locals и globals при использовании eval () Python?
  • Python - лучший язык программирования в мире.