Jest to dość ciekawy przypadek:
>>> def func():
... exec('print "hi from func"')
... def subfunction():
... return True
...
File "<stdin>", line 2
SyntaxError: unqualified exec is not allowed in function 'func' because
it contains a nested function with free variables
Powodem dlaczego to nie działa w rzeczywistości jest to, że subfunction
zawiera zmienną wolną, a ponieważ w Pythonie 2, exec
teoretycznie może zmodyfikować mieszkańców w zawierającym nie można by zdecydować, czy zmienna powinna być związana z zakresem funkcji globalnej czy nadrzędnej. Jeden z wersetów w Zen Pythona to: "W obliczu niejednoznaczności odrzuć pokusę odgadnięcia". i to właśnie robi Python 2.
Teraz pytanie brzmi: co to za zmienna niezwiązana? Cóż, to jest True
!
Rzeczywiście jest powtarzalny z None
:
>>> def func():
... exec('print "hi from func"')
... def subfunction():
... return None
...
File "<stdin>", line 2
SyntaxError: unqualified exec is not allowed in function 'test2' because it contains a nested
function with free variables
Nawet None
nie można przypisać, i jest uważana za stałej w kodu bajtowego, parser buggy uważa, że jest to zmienna niezwiązany tutaj.
Ale jeśli zastąpić go 1
i działa bez problemów:
>>> def test2():
... exec('print "hi from func"')
... def subfunction():
... return 1
...
>>>
Aby uniknąć tego błędu, określa sposobu globalnych i ewentualnie mieszkańców że mają być stosowane przez exec
, słownie:
>>> def test2():
... exec 'print "hi from test2"' in {}
... def subfunction():
... return None
...
>>>
W języku Python 3, exec
jest tylko prostą funkcją i nie jest obsługiwany specjalnie przez analizator składni lub kompilator kodu bajtowego. W języku Python 3 exec
nie można ponownie powiązać nazw lokalnych funkcji, a tym samym nie występuje ten błąd składni i niejednoznaczność.
Jeden szczególny przypadek Pythonie 2 vs 3 zgodność, że podczas gdy stwierdza się, że Python 2.7 documentation
Postać exec(expr, globals)
odpowiada exec expr in globals
, podczas gdy postać exec(expr, globals, locals)
odpowiada exec expr in globals, locals
. Krotki formularz exec
zapewnia kompatybilność z Python 3, gdzie exec
jest funkcją, a nie oświadczeniem.
Krotka forma nie zawsze była w 100% kompatybilna, ponieważ była tam a bug in handling of exec
in functions with nested functions (issue 21591); do Python 2.7.8 następujący kod mógł spowodować wyjątek:
def func():
exec('print "hi from test2"', {})
def subfunction():
return None
Naprawiono to w Pythonie 2.7.9 i już nie rzuca.
Istnieje takie samo ograniczenie z 'import * z ...'. – osa
Wygląda na to, że rozumowanie przez dict uważane jest za podfunkcje. – dbliss