【问题标题】:Mark Lutz confuses me a littleMark Lutz 让我有点困惑
【发布时间】: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关于修改被闭包捕获的变量
  • 这显然是我第一次使用堆栈溢出。我欢迎您的反馈。会有所改善

标签: python function


【解决方案1】:

action 就是我们所说的闭包。它是一个函数对象与一个环境的组合,该环境包含所谓的 free 变量的值,这些变量是函数体中使用的非本地名称。

在这种情况下,action 是一个包含n 值的环境的闭包,它是从对maker 的调用“继承”的,其中定义了action。请注意,对maker 的每次调用都定义了一个名为actionnew 函数对象。调用 maker 返回的闭包由这个新函数和传递给 makern 的值组成。

在实践中,函数和闭包几乎没有区别;它的行为与函数完全一样,只是它的一些非本地名称取自其封闭环境而不是全局或调用范围。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 2021-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多