2012-02-08 3 views
3

Ищите хорошее объяснение, почему этот код вызывает SyntaxError.Любое объяснение поведения exec?

def echo(x): 
    return x 

def foo(s): 
    d = {} 
    exec(s, {}, d) 
    return dict((x,y) for x,y in d.items()) 

def bar(s): 
    d = {} 
    exec(s, {}, d) 
    return dict((x, echo(y)) for x,y in d.items()) # comment this to compile 

s = 'a=1' 
foo(s) 

File "test.py", line 11 
    exec(s, {}, d) 
SyntaxError: unqualified exec is not allowed in function 'bar' it contains a 
      nested function with free variables 
+6

Что же это должно делать? –

+3

@ DanielRoseman: Фактический вопрос выглядит следующим образом: Почему 'foo()' действительный Python, в то время как 'bar()' is not? На мой взгляд, очень правильный вопрос, хотя его следует изложить немного яснее. –

+1

@ DanielRoseman: D Этот код предназначен только для объяснения. Реальный код - гораздо более приемлемая версия. Я просто искал объяснения exec. – Shekhar

ответ

7

В Python 2.x, exec заявления могут не появляться внутри функции, которые имеют локальные "функции" со свободными переменными. Выражение генератора неявно определяет какую-то «функцию» (или, точнее, объект кода) для кода, который должен выполняться на каждой итерации. В foo() этот код содержит только ссылки на x и y, которые являются локальными именами внутри выражения генератора. В bar() код также содержит ссылку на свободную переменную echo, которая дисквалифицирует bar() для использования exec.

отметить также, что ваши exec заявления, вероятно, должны прочитать

exec s in {}, d 

, который превратит их в квалифицированных EXEC заявления, что делает код действителен.

Обратите внимание, что ваш код будет работать в Python 3.x. exec() был превращен в функцию и больше не может изменять локальные переменные закрывающей функции, тем самым делая ненужным ограничение на использование exec.

+0

Отлично. И +1 для подсказки python 3.x. – Shekhar

+1

@Shekhar: Добавлена ​​важная деталь ... –

+0

Спасибо. Также заметил, что «exec in ..» должен работать только для 2.x. – Shekhar

3

Возможно, вы попытаетесь написать код python 2.x с помощью руководства python 3.x. С Python 3.2 я не получаю эту ошибку, а в Python 2.7 синтаксис exec - quite different.

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