2016-12-19 7 views
7

Почему Python's eval не работает внутри функции? Тот же код eval(compile(cmd)) работает в глобальной среде, но не работает внутри функции foo.Python eval не работает внутри функции

Простой пример:

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) 

Это выход и сообщение об ошибке:

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

вы уверены, что вы не хотите, чтобы присвоить его значение к чему-то? –

+0

Просто попробовал это: 'x' заканчивается в' locals' dict, так же, как и с 'exec', но в то время как' exec (cmd) 'работает внутри функции,' eval (compile (...)) ' не. –

+0

Кроме того, если вы поместите 'eval (« x »)' вместо 'x' в' print 'foo: x =', x', он тоже работает. Такое же поведение и в Python 2.7, и в Python 3.4 –

ответ

4

В функции, выполнение делает работу, но x заканчивается в locals(), а затем print заявление пытается найти x в globals() и поэтому поднимает 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) 

Выходы:

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

Просто заметили, что с 'exec',' x' действительно заканчивается как «глобальными», так и «локальными»; сначала я думал, что оба будут давать одинаковые «глобальные» и «местные». Но да, почему он не смотрит на «locals» и почему работает 'eval (« x »)', где 'x' терпит неудачу? –

+2

Я думаю, что область действия переменной определяется во время определения. Таким образом, такие вещи, как 'a =" a "; def print_a(): print (a); a = "c" 'будет вызывать UnboundLocalError. 'eval (" x ")' "создает новый полный поиск" и, следовательно, может изучать локальную область. – syntonym

+0

@syntonym Это интересная теория, которая имеет определенный смысл, учитывая ваш пример, и объясняет поведение. Можете ли вы предоставить ссылку для этого? –

 Смежные вопросы

  • Нет связанных вопросов^_^