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