【发布时间】:2017-09-01 14:06:08
【问题描述】:
第一次浏览函数(没有技术编码背景)我无法理解一个概念,它是这样的。
一个简单的函数工厂:
为了简单地说明这一点,请考虑以下在交互式提示符下键入的函数:
>>> def maker(N):
... def action(X): # Make and return action
... return X ** N # action retains N from enclosing scope
... return action
这定义了一个外部函数,它简单地生成并返回一个嵌套函数,而不调用它——maker 生成动作,但只是返回动作而不运行它。如果我们调用外部函数:
>>> f = maker(2) # Pass 2 to argument N
>>> f
.action at 0x0000000002A4A158>
我们得到的是对生成的嵌套函数的引用——当嵌套的 def 运行时创建的。如果我们现在调用从外部函数返回的内容:
>>> f(3) # Pass 3 to X, N remembers 2: 3 ** 2
9
>>> f(4) # 4 ** 2
16
我们调用嵌套函数——在 maker 中调用 action。换句话说,我们调用的是 maker 创建并传回的嵌套函数。 不过,也许最不寻常的部分是嵌套函数记住整数 2,即 maker 中变量 N 的值,即使 maker 在我们调用该操作时已经返回并退出。实际上,来自封闭本地范围的 N 被保留为附加到生成的动作的状态信息,这就是为什么我们在以后调用它时返回它的参数平方的原因。同样重要的是,如果我们现在再次调用外部函数,我们会返回一个新的嵌套函数,其中附加了不同的状态信息。也就是说,当调用新函数时,我们得到的参数是立方的而不是平方的,但原来的仍然像以前一样平方:
>>> g = maker(3) # g remembers 3, f remembers 2
>>> g(4) # 4 ** 3
64
>>> f(4) # 4 ** 2
这里到底发生了什么。请给我一个我能理解的观点。
【问题讨论】:
-
请尝试改进您问题的标题:目前还不清楚问题的内容。
-
您的描述是正确的,返回的函数保留了一点状态。这称为词法闭包,它是一个函数,在创建函数时包含词法范围内的变量,这些变量被“关闭”并与函数一起保存。但是,我不确定您的问题最终是什么,您是在问这是如何实现的吗?
-
另见stackoverflow.com/q/21959985/124319关于修改被闭包捕获的变量
-
这显然是我第一次使用堆栈溢出。我欢迎您的反馈。会有所改善