Здесь я понял, что это exec(myblock)
, это всегда добавляет объекты к locals()
. Я проверил приведенные ниже сценарии.
Так как python управляет locals
и globals
, когда вы используете exec
.
if (globals == Py_None) {
globals = PyEval_GetGlobals();
if (locals == Py_None) {
locals = PyEval_GetLocals();
if (locals == NULL)
return NULL;
}
if (!globals || !locals) {
PyErr_SetString(PyExc_SystemError,
"globals and locals cannot be NULL");
return NULL;
}
}
else if (locals == Py_None)
locals = globals;
В соответствии с приведенной выше логикой, когда вы делаете exec(myblock, None, None)
питона получает globals()
и работает равным это выражение exec(myblock, globals(), globals())
, как задорно вышеприведенная логика. ниже - простое выражение для проверки, является ли locals() is globals()
или нет, когда мы предоставляем как None
.
>>> exec("print(locals() is globals())", None, None)
True
Таким же образом, когда мы обеспечиваем locals
, как None
, в соответствии с приведенной выше питона логики if (locals == Py_None) locals = globals
, как будет ссылаться на тот же объект, и это globals
.
>>> exec("print(locals() is globals())", globals(), None)
True
И когда мы проходим locals
как пустая Словаре {}
, согласно вышеуказанной логике он не будет делать каких-либо изменений в локальных переменных.
>>> exec("print(locals() is globals())", globals(), {})
False
Теперь давайте посмотрим, Что происходит в вашем случае ..
Я изменил сценарий немного и добавил print(list(globals()), list(locals())); print(locals() is globals())
эти две строки, как показано ниже.
myblock = """
def iszero(x):
return x == 0
args = [0, 1, 2]
# added these two stmts here
print(list(locals()))
print(list(globals()))
print(locals() is globals())
flts = list(filter(lambda f:(not iszero(f)), args)) #NameError
"""
И после выполнения указанных выше строк с помощью exec
с locals
, как пустым Dict.
>>> exec(myblock, globals(), {})
['iszero', 'args']
['__package__', 'myblock', '__builtins__', '__spec__', '__doc__', '__loader__', '__name__']
False
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 12, in <module>
File "<string>", line 12, in <lambda>
NameError: name 'iszero' is not defined
Очевидно, что locals
пространство это получение добавлены все атрибуты. поэтому вы никогда не увидели бы iszero
метод в globals
, если вы пройдете locals
как {}
.
И причина вы получаете NameError
для закрытия list(filter(lambda f:(not iszero(f)), args))
он начал поиск в globals
вместо locals
и ваших Глобал не метод определен.
Могу ли я спросить, почему ваш скрипт использует не только 'lambda', но также' exec() 'и' globals() '? – TigerhawkT3
@ user5090812 Вы подаете в суд на 'Python3'? –
@ gsb-eng 'Python 3.4.3' – user5090812