Traceback (most recent call last): File "<pyshell#6>", line 1, in <module> foo() File "<pyshell#5>", line 4, in foo print(xyz) NameError: global name 'xyz'isnot defined
Изменение locals() не определено. Вне функции, когда locals() и globals() совпадают, это будет работать; внутри функции это обычно не будет работать.
Используйте словарь или задайте атрибут для объекта:
d = {} d['xyz'] = 42 print(d['xyz'])
или, если вы предпочитаете, используйте класс:
classC: pass
obj = C() setattr(obj, 'xyz', 42) print(obj.xyz)
Редактировать: Доступ к переменным в пространствах имен, которые не являются функциями (таким образом, модули, определения классов, экземпляры), обычно осуществляется путем поиска по словарю (как указывает Sven в комментариях, существуют исключения, например классы, которые определяют __slots__). Локальные значения функций могут быть оптимизированы для повышения скорости, потому что компилятор (обычно) знает все имена заранее, поэтому словаря нет, пока вы не вызовете locals().
В реализации Python на языке Си locals() (вызывается изнутри функции) создает обычный словарь, инициализированный текущими значениями локальных переменных. Внутри каждой функции любое количество вызовов locals() вернет один и тот же словарь, но каждый вызов locals() обновит его текущими значениями локальных переменных. Это может создать впечатление, что присваивание элементам словаря игнорируется (изначально я писал, что это так). Изменения существующих ключей в словаре, возвращаемые из locals() следовательно, сохраняются только до следующего вызова locals() в той же области видимости.
В IronPython все работает немного по-другому. Любая функция, которая вызывается locals() внутри нее, использует словарь для своих локальных переменных, поэтому присвоения локальных переменных изменяют словарь, а присвоения словарю изменяют переменные, НО это только в том случае, если вы явно вызываете locals() под этим именем. Если вы привяжете другое имя к locals функции в IronPython, то при ее вызове вы получите локальные переменные для области, в которой было привязано имя, и нет способа получить доступ к локальным функциям через нее:
Все это может измениться в любой момент. Единственное, что гарантировано, это то, что вы не можете зависеть от результатов присвоения словарю, возвращаемого locals().
Ответ 2
Другие предлагали присвоить значение locals(). Это не будет работать внутри функции, где доступ к локальным файлам осуществляется с помощью LOAD_FAST кода операции, если у вас нет exec инструкции где-нибудь в функции. Для поддержки этого оператора, который может создавать новые переменные, неизвестные во время компиляции, Python затем вынужден обращаться к локальным переменным по имени внутри функции, поэтому запись в locals() работает. exec Может находиться вне пути к исполняемому коду.
deffunc(varname): locals()[varname] = 42 return answer # only works if we passed in "answer" for varname exec""# never executed
func("answer") >>> 42
Примечание: Это работает только в Python 2.x. Они покончили с этой глупостью в Python 3, и другие реализации (Jython, IronPython и т.д.) Также могут ее не поддерживать.
Однако это плохая идея. Как вы получите доступ к переменным, если не знаете их названия? По locals()[xxx] вероятно. Так почему бы просто не использовать свой собственный словарь, а не загрязнять его locals() (и не рисковать перезаписью переменной, которая действительно нужна вашей функции)?
Ответ 3
(Просто небольшое замечание для тех, кто гуглит)
Ок, значит, изменять locals()не стоит (в то время как изменение globals()должно работать). В то же время, execможет быть, но это мучительно медленно, поэтому, как и в случае с регулярными выражениями, мы можем захотеть compile() это сделать в первую очередь:
# var0 = 0; var1 = 1; var2 = 2 code_text = '\n'.join( "var%d = %d" % (n, n) for n in xrange(3) )