我了解闭包的基本知识。我在学习python时遇到的一些问题的常见示例是:
def maker(N):
def action(X):
return X ** N
return action
我了解运行制造商的结果,并且我知道即使制造商封闭了范围,行动仍保留了一些状态信息N。我也了解到N的不同值存储在不同的号召性用语中。但是我不明白的是,解释器如何“知道”在操作中引用了N。
如果一个函数的主体仅在调用该函数时运行,那么解释器怎么可能甚至知道将N的数据与嵌套的动作函数相关联?我想也许当存在这样的嵌套结构时,python可能会在内部查看是否有任何引用。我尝试过:
def f1():
def f2():
print(undefined_variable)
如果是python检查嵌套函数以确定它们是否在封闭范围内引用变量的情况,那么当遇到f2中的未定义变量时,它还会抛出错误吗?我的猜测是不会这样做(因为即使在调用f1的情况下也不会在这里吐出错误)。
所以我的问题是,如果那些嵌套函数的主体直到被调用时才执行,那么python如何知道将范围内的名称与嵌套函数相关联?
答案 0 :(得分:3)
要为@DYZ的答案添加更多细节,请尝试以下区别:
def foo(a):
return lambda b: a * b
def foo2(a):
return lambda b: locals()['a'] * b
def foo3(a):
def bar(b):
return locals()['a'] * b
print('not executed', a)
return bar
foo(3)(5)
成功评估为15 foo2(3)(5)
无法评估,因为解析器不“知道”以后将需要a
foo3(3)(5)
之所以成功,是因为它知道以后需要a
,因此建立了一个绑定它的闭包。如果字节码生成更智能,则可能会意识到print
无法访问,因此无法构建闭包,但是在Python 3.7中它对我没有作用 dis
module可能使Python在幕后所做的事情更加明显,例如:
from dis import dis
dis(foo)
打印出与foo
关联的字节码,尝试与其他功能进行比较