2016-12-19 62 views
7

Dlaczego Python's eval nie działa w funkcji? Ten sam kod eval(compile(cmd)) działa w środowisku globalnym, ale nie działa wewnątrz funkcji foo.Python eval nie działa wewnątrz funkcji

Prosty przykład:

fn = '/tmp/tmp' 
mode = 'single' 

def foo(cmd, fn, mode): 
    eval(compile(cmd, fn, mode)) # <<< this does not work 
    print 'foo: cmd=', cmd 
    print 'foo: x=', x 

cmd = "x = 1" 
eval(compile(cmd, fn, mode)) # <<< this works 
print 'global scope: cmd=', cmd 
print 'global scope: x=', x 

del(x) 
foo('x = 9', fn, mode) 

Jest to przesłanie wyjścia i błędów:

global scope: cmd= x = 1 
global scope: x= 1 
foo: cmd= x = 9 
foo: x= 
Traceback (most recent call last): 
    File "ctest.py", line 20, in <module> 
    foo('x = 9', fn, mode) 
    File "ctest.py", line 12, in foo 
    print 'foo: x=', x 
NameError: global name 'x' is not defined 
+0

jesteś pewien, że nie chcesz, aby przypisać jej wartość do czegoś? –

+0

Po prostu próbowałem tego: 'x' kończy się w' locals' dict, podobnie jak w 'exec', ale gdy' exec (cmd) 'działa w funkcji,' eval (kompilacja (...)) ' nie. –

+0

Również, jeśli wstawisz 'eval (" x ")' zamiast 'x' w' print 'foo: x =', x' to też działa. To samo zachowanie zarówno w Pythonie 2.7, jak i Pythonie 3.4 –

Odpowiedz

4

W swojej funkcji, wykonanie działa ale x kończy się w locals(), a następnie print oświadczenie stara Aby znaleźć x w globals(), a więc podnosi NameError.

fn = '/tmp/tmp' 
mode = 'single' 

def foo(cmd, fn, mode): 
    eval(compile(cmd, fn, mode)) 
    print 'locals:', locals() 
    print 'foo: cmd=', cmd 
    print 'foo: x=', locals()['x'] 

cmd = "x = 1" 
eval(compile(cmd, fn, mode)) 
print 'global scope: cmd=', cmd 
print 'global scope: x=', x 

del(x) 
foo('x = 9', fn, mode) 

Wyjścia:

global scope: cmd= x = 1 
global scope: x= 1 
locals: {'x': 9, 'cmd': 'x = 9', 'mode': 'single', 'fn': '/tmp/tmp'} 
foo: cmd= x = 9 
foo: x= 9 
+1

Po prostu zauważyłem, że w przypadku 'exec',' x' faktycznie kończy się zarówno na 'globals' i' locals'; na początku myślałem, że oba przyniosą identyczne "globals" i "locals". Ale tak, dlaczego nie wygląda na "locals", i dlaczego działa 'eval (" x ")', gdzie 'x' kończy się niepowodzeniem? –

+2

Myślę, że zakres zmiennej w funkcji jest określana w czasie definicji. Tak więc rzeczy takie jak "a =" a "; def print_a(): print (a); a = "c" 'wyrzuci UnboundLocalError. 'eval (" x ")' "tworzy nowe pełne wyszukiwanie", dzięki czemu można zajrzeć do lokalnego zakresu. – syntonym

+0

@syntonym To interesująca teoria, która ma jakiś sens, biorąc pod uwagę twój przykład i wyjaśniająca zachowanie. Czy możesz podać referencję? –