小白学 Python
课程GitHub
© 2026 小白学 Python · 基于 walter201230/Python 教程
课程目录GitHub
Python 环境加载中…
闭包0 / 3
123

闭包

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

教学 02 / 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
  • 全局变量降低了模块之间的通用性——大家都依赖它
  • 全局变量降低了代码的可读性——阅读者不知道某个名字到底是哪儿来的

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

教学 01 / 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,并做几道练习。

练习 3 / 3·用闭包实现计数器🔒 完成上一题后解锁题目有问题?

请定义一个函数 make_counter():

  • 内部维护一个 count = 0
  • 返回一个内层函数 counter(),每次调用 counter() 时让 count + 1 并返回新值(记得用 nonlocal)

然后:

  1. c = make_counter()
  2. 连续调用 3 次 c(),每次都 print 它的返回值

输出应该是:

1
2
3
main.py
🔒 未解锁
🔒做对当前题解锁下一段 ·0/3
本章目录

闭包

  1. 教学 02第十五节:闭包
  2. 教学 01一、什么是闭包
  3. 练习 3 🔒用闭包实现计数器
  4. 教学 03二、nonlocal 关键字
  5. 练习 1加法器工厂
  6. 教学 04三、闭包的实用场景
  7. 练习 2 🔒用闭包累加学习时间
← 上一章14 · 正则表达式
闭包
下一章 →16 · 装饰器