Я пытаюсь запустить кусок кода python с помощью exec.
my_code = """
class A(object):
pass
print 'locals: %s' % locals()
print 'A: %s' % A
class B(object):
a_ref = A
"""
global_env = {}
local_env = {}
my_code_AST = compile(my_code, "My Code", "exec")
exec(my_code_AST, global_env, local_env)
print local_env
что приводит к следующему выводу
locals: {'A': <class 'A'>}
A: <class 'A'>
Traceback (most recent call last):
File "python_test.py", line 16, in <module>
exec(my_code_AST, global_env, local_env)
File "My Code", line 8, in <module>
File "My Code", line 9, in B
NameError: name 'A' is not defined
Однако, если я изменю код на это -
my_code = """
class A(object):
pass
print 'locals: %s' % locals()
print 'A: %s' % A
class B(A):
pass
"""
global_env = {}
local_env = {}
my_code_AST = compile(my_code, "My Code", "exec")
exec(my_code_AST, global_env, local_env)
print local_env
тогда он отлично работает - дает следующий вывод -
locals: {'A': <class 'A'>}
A: <class 'A'>
{'A': <class 'A'>, 'B': <class 'B'>}
Ясно, что A присутствует и доступно - что происходит в первом фрагменте кода? Я использую 2.6.5, приветствия,
Колин
* ОБНОВЛЕНИЕ 1 *
Если я проверил locals() внутри класса -
my_code = """
class A(object):
pass
print 'locals: %s' % locals()
print 'A: %s' % A
class B(object):
print locals()
a_ref = A
"""
global_env = {}
local_env = {}
my_code_AST = compile(my_code, "My Code", "exec")
exec(my_code_AST, global_env, local_env)
print local_env
Тогда становится ясно, что locals() не одинаковы в обоих местах -
locals: {'A': <class 'A'>}
A: <class 'A'>
{'__module__': '__builtin__'}
Traceback (most recent call last):
File "python_test.py", line 16, in <module>
exec(my_code_AST, global_env, local_env)
File "My Code", line 8, in <module>
File "My Code", line 10, in B
NameError: name 'A' is not defined
Однако, если я это сделаю, проблем нет -
def f():
class A(object):
pass
class B(object):
a_ref = A
f()
print 'Finished OK'
* ОБНОВЛЕНИЕ 2 *
ok, поэтому документы здесь - http://docs.python.org/reference/executionmodel.html
'Определение класса - это исполняемый оператор, который может использовать и определять имена. Эти ссылки соответствуют нормальным правилам разрешения имен. Пространство имен определения класса становится атрибутом словаря класса. Имена, определенные в области класса, не видны в методах. '
Мне кажется, что "A" должно быть доступно как свободная переменная внутри исполняемого оператора, который является определением B, и это происходит, когда мы вызываем f() выше, но не тогда, когда мы используем exec(). Это можно более легко показать со следующим -
my_code = """
class A(object):
pass
print 'locals in body: %s' % locals()
print 'A: %s' % A
def f():
print 'A in f: %s' % A
f()
class B(object):
a_ref = A
"""
который выводит
locals in body: {'A': <class 'A'>}
A: <class 'A'>
Traceback (most recent call last):
File "python_test.py", line 20, in <module>
exec(my_code_AST, global_env, local_env)
File "My Code", line 11, in <module>
File "My Code", line 9, in f
NameError: global name 'A' is not defined
Итак, я думаю, новый вопрос: почему не те локальные жители подвергаются как свободные переменные в определениях функций и классов - это похоже на довольно стандартный сценарий закрытия.