Ответ 1
Короче говоря, поскольку eval
предназначен для динамической оценки, интерпретатор не знает, что он должен добавить a
в локальную область g
. Для эффективности интерпретатор не будет добавлять ненужные переменные в dict
локальных переменных.
Из документа для eval
:
Аргумент выражения анализируется и оценивается как выражение Python (с технической точки зрения, список условий), используя глобалы и словари locals как глобальное и локальное пространство имен.
Это означает, что функции eval(expression)
будут использовать globals()
как глобальную область по умолчанию и locals()
как свою локальную область, если ни одна из них не предоставляется.
Хотя, в вашем первом примере нет a
в одном.
def f(a):
print("f locals:", locals())
def g():
print("g locals:", locals())
print(eval('a'))
return g()
f(1)
Действительно, поскольку интерпретатор не видит ссылки на a
при анализе тела g
, он не добавляет его к своим локальным переменным.
Чтобы он работал, вам нужно указать nonlocal a
в g
.
Выход
f locals: {'a': 1}
g locals: {}
Traceback ...
...
NameError: name 'a' is not defined
В вашем втором примере a
находится в g
локальных переменных, так как используется в области.
def f(a):
print("f locals:", locals())
def g():
print("g locals:", locals())
b = a + 1
print("g locals after b = a + 1:", locals())
print(eval('a'))
return g()
f(1)
Выход
f locals: {'a': 1}
g locals: {'a': 1}
g locals after b = a + 1: {'a': 1, 'b': 2}
1