小白学 Python
AI 编程指南GitHub
© 2026 小白学 Python · 基于 walter201230/Python 教程
课程目录关于本站联系方式隐私政策GitHub
Python 环境加载中…
闭包0 / 3
123

闭包

3 道练习题·预计 25 分钟·做对一题解锁下一段

教学 01 / 04· 已读

第十五节:闭包

这一节我们通过解决一个实际需求来认识闭包。

需求:累加学习时间

我们需要一直记录自己的学习时间,以分钟为单位。比如:

  • 第一次学习了 2 分钟,返回 2
  • 隔了一会儿又学习了 10 分钟,返回 12(累加)
  • 一直累加下去……

最直觉的写法是用一个全局变量记录时间,然后用一个函数往里加:

python
time = 0

def insert_time(min):
    time = time + min
    return time

print(insert_time(2))
print(insert_time(10))

认真想一下,这段代码会有什么问题呢?

直接报错

其实,这段代码在 Python 里会报错:

UnboundLocalError: local variable 'time' referenced before assignment

为什么?因为在 Python 中,如果一个函数里给一个名字赋值了,这个名字就被认为是局部变量——哪怕外面有同名的全局变量。函数内 time = time + min 这一行,time 已经被当成局部变量了,但右边又先去取它的值,所以报「先用后定义」。

用 global 关键字?

如果确实要在函数中引用并修改全局变量,可以用 global 关键字:

python
time = 0

def insert_time(min):
    global time
    time = time + min
    return time

print(insert_time(2))
print(insert_time(10))

输出:

2
12

可是啊,这里使用了全局变量——开发中能避免就尽量避免。

为什么?

  • 不同模块、不同函数都能自由访问、修改全局变量,会造成不可预知的 bug
  • 全局变量降低了模块之间的通用性——大家都依赖它
  • 全局变量降低了代码的可读性——阅读者不知道某个名字到底是哪儿来的

那有没有更优雅的办法呢?这就是闭包登场的时候了。

教学 02 / 04

一、什么是闭包

1、用闭包解决累加问题

我们直接看代码:

python
def study_time(time):
    def insert_time(min):
        nonlocal time
        time = time + min
        return time

    return insert_time


f = study_time(0)
print(f(2))
print(f(10))

输出:

2
12

这就是闭包——「函数里嵌套函数,内层函数返回出去带着外层变量」。

2、闭包的定义

当一个内部函数被当作对象返回时,它夹带了外部函数的局部变量,就形成了一个闭包。

换句话说:内部函数的局部作用域中可以访问外部函数局部作用域中的变量,这种行为就叫闭包(Closure)。

回头看上面的代码:

python
def study_time(time):              # 外层函数:接收一个 time
    def insert_time(min):          # 内层函数:实现累加逻辑
        nonlocal time
        time = time + min
        return time

    return insert_time             # 外层返回内层函数对象(在 Python 中,函数也是对象)


f = study_time(0)                  # 调用 study_time,f 现在等于 insert_time 函数
print(f(2))                        # 相当于调用 insert_time(2)
print(f(10))                       # 相当于调用 insert_time(10)

f 不是数字,不是字符串——它是一个带着 time 这个变量的函数。每次调用 f 时,那个 time 还在它身边,所以累加可以一直延续。

3、闭包的好处

  • 避免使用全局变量 —— 数据藏在闭包里,不污染全局
  • 把函数和它操作的数据「绑定」起来 —— 类似一个超轻量的对象
  • 是后面要学的装饰器的基础

听起来挺玄,下一节我们会重点讲让闭包修改外层变量的关键字 nonlocal,并做几道练习。

练习 1 / 3·加法器工厂题目有问题?

请定义一个函数 make_adder(n):

  • 接收一个数字 n
  • 返回一个内层函数 adder(x),作用是返回 x + n

然后:

  1. 用 make_adder(10) 生成 add10
  2. print(add10(5)) —— 应该输出 15
  3. 用 make_adder(100) 生成 add100
  4. print(add100(5)) —— 应该输出 105

输出应该是:

15
105
main.py
可编辑
🔒做对当前题解锁下一段 ·0/3

推荐一个,全网最全最友好的中文 AI 编程指南: coding.stormzhang.ai

← 上一章14 · 正则表达式
闭包
下一章 →16 · 装饰器
本章目录

闭包

  1. 教学 01第十五节:闭包
  2. 教学 02一、什么是闭包
  3. 练习 1加法器工厂
  4. 教学 03二、nonlocal 关键字
  5. 练习 2 🔒用闭包实现计数器
  6. 教学 04三、闭包的实用场景
  7. 练习 3 🔒用闭包累加学习时间