Эта проблема несколько обсуждается в списке ошибок Python3 . В конечном счете, чтобы получить это поведение, вам нужно сделать:
def foo():
ldict = {}
exec("a=3",globals(),ldict)
a = ldict['a']
print(a)
И если вы проверите документацию Python3 на exec
, вы увидите следующее примечание:
Локали по умолчанию действуют, как описано для функции
blockquote>locals()
ниже: не следует пытаться модифицировать словарь локальных файлов по умолчанию. Передайте явный словарь locals, если вам нужно увидеть эффекты кода на локалях после возврата функции exec ().Обратившись к к определенному сообщению в отчете об ошибке , Георг Брандл говорит:
Для изменения локалей функции «на лету» невозможно без нескольких последствий: обычно локаторы функций не хранятся в словаре, а массиве, индексы которого определяются во время компиляции из известных локалей. Это сталкивается, по крайней мере, с новыми локалями, добавленными exec. Старая инструкция exec обошла это, потому что компилятор знал, что если в функции произошел exec без globals / locals args, это пространство имен будет «неоптимизировано», то есть не будет использовать массив locals. Поскольку exec () теперь является нормальной функцией, компилятор не знает, к чему «exec» может быть привязан, и поэтому не может быть обработан специально.
blockquote>Акцент мой.
Таким образом, суть в том, что Python3 может лучше оптимизировать использование локальных переменных с помощью not , позволяя это поведение по умолчанию.
И ради полноты, как упомянутый в комментариях выше, этот работает , как и ожидалось в Python 2.X:
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) [GCC 4.3.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> def f(): ... a = 1 ... exec "a=3" ... print a ... >>> f() 3