0Pricing
Python Academy · 课时

闭包与自由变量

在内部函数中捕获状态

闭包与自由变量 是 CoddyKit 上的免费 Python Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。

嵌套函数

Python 允许您在一个函数内部定义另一个函数。每次 outer 函数运行时,都会重新创建 inner 函数。

def outer():
    def inner():
        return 'from inner'
    return inner()
print(outer())

inner 可以看到 outer 变量

inner 函数可以读取外层函数中定义的变量。这些变量称为自由变量,因为它们不是 inner 函数的局部变量。

def outer():
    message = 'hello'
    def inner():
        return message
    return inner()
print(outer())

什么是闭包

当 inner 函数被返回后,即使外层作用域已经结束,它仍然记得来自外层作用域的自由变量,这种情况就称为闭包。

def make_greeter(name):
    def greet():
        return 'Hi ' + name
    return greet
g = make_greeter('Ada')
print(g())

捕获的状态会保留下来

outer 函数已经返回了,但闭包仍然持有 name。这个值会继续存在于返回的函数内部。

def make_greeter(name):
    def greet():
        return 'Hi ' + name
    return greet
a = make_greeter('Ada')
b = make_greeter('Bob')
print(a())
print(b())

乘法器工厂

闭包非常适合用作生成定制函数的工厂。这里返回的每个函数都会乘以一个捕获的因子。

def multiplier(factor):
    def multiply(n):
        return n * factor
    return multiply
double = multiplier(2)
triple = multiplier(3)
print(double(10))
print(triple(10))

每个闭包彼此独立

工厂的每次调用都会创建一个独立的闭包,并拥有各自捕获的值。它们互不影响。

def adder(amount):
    def add(n):
        return n + amount
    return add
add5 = adder(5)
add100 = adder(100)
print(add5(1), add100(1))

检查闭包捕获的值

捕获的名称会列在 __code__.co_freevars 中,而这些名称对应的值存储在 __closure__ 单元中。

def make(x):
    def f():
        return x
    return f
fn = make(42)
print(fn.__code__.co_freevars)
print(fn.__closure__[0].cell_contents)

闭包捕获变量而不是值

闭包捕获的是变量本身,因此它看到的是变量的最终值。当变量在闭包创建后发生变化时,这一点就很重要。

def build():
    x = 1
    def show():
        return x
    x = 99
    return show
print(build()())

循环中的延迟绑定陷阱

一个经典的易错点是:循环中创建的闭包共享同一个循环变量,因此它们捕获的都是该变量的最后一个值。

funcs = []
for i in range(3):
    funcs.append(lambda: i)
print([f() for f in funcs])

修复延迟绑定

使用默认参数绑定当前值,这样每个闭包就能在定义时捕获自己的副本。

funcs = []
for i in range(3):
    funcs.append(lambda i=i: i)
print([f() for f in funcs])

闭包作为轻量级对象

闭包将数据与行为组合在一起,就像一个小型对象;对于简单情况,它通常比完整的类更简洁。

def counter_start(start):
    def value():
        return start
    return value
c = counter_start(10)
print(c())

快速检查

Python 中的闭包是什么?

回顾:闭包与自由变量

要点:

  • inner 函数可以读取外层作用域中的变量(自由变量)。
  • 闭包是一个被返回且会记住这些变量的 inner 函数。
  • 工厂的每次调用都会创建一个独立的闭包。
  • 闭包捕获的是变量而不是值,这会导致循环中的延迟绑定陷阱——可以使用默认参数修复。
def power_of(exp):
    return lambda base: base ** exp
square = power_of(2)
print(square(9))

常见问题解答

「闭包与自由变量」课时是免费的吗?

是的 — 「闭包与自由变量」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。

「闭包与自由变量」这节课中我会学到什么?

在内部函数中捕获状态 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Python Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「闭包与自由变量」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Python Academy 课中编写并运行代码吗?

能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 一等函数
  2. 闭包与自由变量
  3. nonlocal 与可变状态
  4. 偏函数
← 返回 Python Academy