Не забудьте перезапустить Visual Studio после того, как вы сделали Set-ExecutionPolicy Unrestricted
в PowerShell (x86).
Если это не сработает, попробуйте Set-ExecutionPolicy RemoteSigned
в PowerShell (x86), а затем перезапустите Visual Studio .
Эта проблема несколько обсуждается в списке ошибок Python3 . В конечном счете, чтобы получить это поведение, вам нужно сделать:
def foo():
ldict = {}
exec("a=3",globals(),ldict)
a = ldict['a']
print(a)
И если вы проверите документацию Python3 на exec
, вы увидите следующее примечание:
Локали по умолчанию действуют, как описано для функции
locals()
ниже: не следует пытаться модифицировать словарь локальных файлов по умолчанию. Передайте явный словарь locals, если вам нужно увидеть эффекты кода на локалях после возврата функции exec ().Обратившись к к определенному сообщению в отчете об ошибке , Георг Брандл говорит:
Для изменения локалей функции «на лету» невозможно без нескольких последствий: обычно локаторы функций не хранятся в словаре, а массиве, индексы которого определяются во время компиляции из известных локалей. Это сталкивается, по крайней мере, с новыми локалями, добавленными exec. Старая инструкция exec обошла это, потому что компилятор знал, что если в функции произошел exec без globals / locals args, это пространство имен будет «неоптимизировано», то есть не будет использовать массив locals. Поскольку exec () теперь является нормальной функцией, компилятор не знает, к чему «exec» может быть привязан, и поэтому не может быть обработан специально.
Акцент мой.
Таким образом, суть в том, что 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
Причина, по которой вы не можете изменять локальные переменные внутри функции, используя exec
таким образом, и почему exec
действует так, как это делается, можно суммировать следующим образом:
exec
- это функция, которая разделяет ее локальную область действия с областью самой внутренней области, в которой она вызвана. local()
. Когда вы определяете новый объект в exec
, то, что он делает, примерно эквивалентно следующему: from copy import copy
class exec_type:
def __init__(self, *args, **kwargs):
# default initializations
# ...
self.temp = copy(locals())
def __setitem__(self, key, value):
if var not in locals():
set_local(key, value)
self.temp[key] = value
temp
- временное пространство имен, которое сбрасывается после каждого экземпляра (каждый время, которое вы вызываете exec
).
Более подробный пример будет примерно следующим:
g_var = 5
def test():
l_var = 10
print(locals())
exec("print(locals())")
exec("g_var = 222")
exec("l_var = 111")
exec("print(locals())")
exec("l_var = 111; print(locals())")
exec("print(locals())")
print(locals())
def inner():
exec("print(locals())")
exec("inner_var = 100")
exec("print(locals())")
exec("print([i for i in globals() if '__' not in i])")
print("Inner function: ")
inner()
print("-------" * 3)
return (g_var, l_var)
print(test())
exec("print(g_var)")
Выход:
{'l_var': 10}
{'l_var': 10}
locals являются одинаковыми
{'l_var': 10, 'g_var': 222}
после добавления g_var
и изменения l_var
он добавляет только g_var
и оставил неизменяемый l_var
{'l_var': 111, 'g_var': 222}
l_var
, потому что мы меняем и печатаем местные жители в одном экземпляре (один вызов exec)
{'l_var': 10, 'g_var': 222}
{'l_var': 10, 'g_var': 222}
В локальных локалях функции и локальном l_var
exec не изменяется, а g_var
добавлен
Inner function:
{}
{'inner_var': 100}
{'inner_var': 100}
inner_function
. Локальная такая же, как и локальная команда exec
['g_var', 'test']
global содержит только g_var
и имя функции (после исключения специальных методов)
---------------------
(5, 10)
5
Если вы находитесь внутри метода, вы можете сделать это:
class Thing():
def __init__(self):
exec('self.foo = 2')
x = Thing()
print(x.foo)
ldict
, а неdict
? Во всяком случае, я больше не работаю на Python, так что если это не так, мы надеемся, что кто-то еще перезвонит. – Mark Rushakoff 12 September 2013 в 07:20