惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
博客园_首页
N
News | PayPal Newsroom
有赞技术团队
有赞技术团队
The Hacker News
The Hacker News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
S
SegmentFault 最新的问题
Jina AI
Jina AI
人人都是产品经理
人人都是产品经理
P
Privacy & Cybersecurity Law Blog
AI
AI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Schneier on Security
Schneier on Security
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
量子位
Forbes - Security
Forbes - Security
爱范儿
爱范儿
云风的 BLOG
云风的 BLOG
SecWiki News
SecWiki News
Last Week in AI
Last Week in AI
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tor Project blog
Recorded Future
Recorded Future
A
About on SuperTechFans
J
Java Code Geeks
The Register - Security
The Register - Security
PCI Perspectives
PCI Perspectives
H
Hacker News: Front Page
V2EX - 技术
V2EX - 技术
S
Secure Thoughts
V
Vulnerabilities – Threatpost
Hacker News: Ask HN
Hacker News: Ask HN
MongoDB | Blog
MongoDB | Blog
N
Netflix TechBlog - Medium
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Scott Helme
Scott Helme
T
The Exploit Database - CXSecurity.com
Y
Y Combinator Blog
AWS News Blog
AWS News Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
IT之家
IT之家
T
The Blog of Author Tim Ferriss
G
Google Developers Blog
C
CERT Recently Published Vulnerability Notes
L
LangChain Blog
F
Full Disclosure
Application and Cybersecurity Blog
Application and Cybersecurity Blog
The GitHub Blog
The GitHub Blog

博客园 - 箫笛

Tkinter - Button 组件 Tkinter - Label 组件 Tkinter - tk 变量 Tkinter - 事件与绑定 Tkinter - 几何管理器 Tkinter - 核心概念 Tkinter - 快速开始 Tkinter - 介绍 Python 编程 - 条件表达式 Python 编程 - 星号下划线参数释义 shell 编程 - shell 脚本的交互方式 Python insall - macOS 系统安装python的几种方式 Miniconda - Python 环境管理工具 Tkinter - Python GUI 开发 Python 编程 - 下划线命名的区别 Python 编程 - 元类编程 Python 编程 - 多重继承与MRO Python 编程 - 描述符协议 Python 编程 - 类型注解 Python 编程 - 生成器表达式 Python 编程 - 集合 Python 编程 - 装饰器 Python 编程 - 列表推导式 Python 编程 - 函数式编程 Python 编程 - lambda 函数 Python 编程 - 文件操作 Python 编程 - 输入与输出 Python 编程 - 面向对象编程 Python 编程 - 元组(tuple) Python 编程 - 字符串(str) Python 编程 - 字典(dict) Python 编程 - 列表(list) Python 编程 - 数据类型和数据结构 Python 编程 - 语句 Python 编程 - 函数 windows - WSL 的安装与使用 shell编程 - dialog 程序使用指南 FE Team - 如何做好前端代码审查 git 提交的撤销和恢复 React15 - redux-saga 如何在saga中实现轮询接口调用? React15 - React CSS Modules BEM命名实践 React15 - React 15 中 componentWillReceiveProps 为什么会多次调用, 同时componentDidUpdate 也会多次调用? React15 - React15类组件多次执行render方法的原因? React15 - React15应用中代码逻辑复用方案 React15 - React状态同步问题解决 React15 - React 15 中 React.pureComponent 的使用场景 React15 - React 15应用在页面渲染时会多次执行类组件的render 函数的原因 React15 - React 15 中能用 componetDidUpdate 代替 componentWillReceiveProps 吗? React15 - React 15 生命周期函数详解 React15 - 如何在React 15中实现自定义的事件订阅与发送(例如组件间通信) React15 - React15应用中的事件订阅和发送机制 React15 - CSS中的BEM规范 React15 - React CSS Modules BEM命名实践 React15 - 写sass 样式文件,嵌套的结构好,还是扁平的结构好? React15 - sass 中 @mixin 和 @extend 的区别是什么? React15 - React 15 应用 如何使用Css moudules 方式进行模块化开发 React15 - React15应用Sass使用指南 React15 - React 15 应用如何进行性能优化?
Python 编程 - 闭包
箫笛 · 2026-06-21 · via 博客园 - 箫笛

在 Python 3 中,闭包(Closure) 是指在一个嵌套函数中,内部函数引用了外部函数的自由变量(即外部函数作用域中的变量),并且外部函数返回了内部函数本身。这样,即使外部函数执行完毕,内部函数依然可以记住并访问那些被引用的外部变量,形成了一种“闭包”环境。


闭包的三个必要条件

  1. 必须有一个嵌套函数(函数内部定义另一个函数)。
  2. 内部函数必须引用外部函数的变量(非全局变量)。
  3. 外部函数必须返回内部函数(或者把内部函数传给其他对象)。

最简单的闭包示例

def outer(x):
    def inner(y):
        return x + y
    return inner

add_5 = outer(5)       # 返回 inner 函数,并记住了 x=5
print(add_5(3))        # 输出 8
print(add_5(10))       # 输出 15

在这里,inner 引用了外部函数 outer 的局部变量 x。即使 outer 执行完毕,add_5 仍然持有 x=5 的值,这就是闭包。


如何查看闭包中捕获的变量

可以通过函数的 __closure__ 属性查看:

def outer(x):
    def inner(y):
        return x + y
    return inner

f = outer(10)
print(f.__closure__)      # (<cell at 0x...: int object at 0x...>,)
print(f.__closure__[0].cell_contents)  # 10

闭包与 nonlocal 关键字

如果内部函数需要修改外部函数的变量(而不是仅仅读取),必须使用 nonlocal 声明,否则 Python 会认为你在内部函数中新建了一个局部变量。

def counter():
    count = 0
    def increment():
        nonlocal count   # 声明 count 不是局部变量
        count += 1
        return count
    return increment

c = counter()
print(c())  # 1
print(c())  # 2

如果没有 nonlocalcount += 1 会抛出 UnboundLocalError


闭包的常见应用场景

  • 装饰器(Decorator):闭包是实现装饰器的核心机制,装饰器接受函数,在内部包装并返回新函数。
  • 工厂函数:生成带有特定配置的函数(如上面的 outer)。
  • 回调函数:在事件驱动或异步编程中,携带额外状态。
  • 函数式编程:实现柯里化(Currying)、部分应用等。

注意事项

  1. 变量生命周期:闭包会延长外部变量的生命周期,它们不会在外部函数返回后立即释放,而是随闭包函数一起存在。如果大量使用闭包且不注意,可能导致内存泄漏。
  2. 循环中的闭包陷阱:在循环中创建闭包时,如果内部函数引用了循环变量,往往得到意外的结果(所有函数共享同一个变量)。解决方案是使用默认参数或 functools.partial
# 错误示例
funcs = []
for i in range(3):
    funcs.append(lambda: i)   # 所有 lambda 都引用同一个 i
print(funcs[0]())  # 2
print(funcs[1]())  # 2
print(funcs[2]())  # 2

# 正确做法:用默认参数捕获当前值
funcs = []
for i in range(3):
    funcs.append(lambda i=i: i)  # 默认参数在定义时求值
print(funcs[0]())  # 0
print(funcs[1]())  # 1
print(funcs[2]())  # 2
  1. 性能:闭包比普通函数调用稍慢,因为涉及自由变量的访问(通过 LOAD_DEREF 指令),但在大多数场景下可忽略。

与 Python 2 的区别

  • Python 2 中,闭包只能读取外部变量,不能修改(没有 nonlocal)。Python 3 引入了 nonlocal,使得修改外层非全局变量成为可能。
  • Python 3 对闭包的实现更加清晰,__closure__ 属性统一。

总结

闭包是 Python 函数式编程的重要基石,理解它有助于掌握装饰器、高阶函数等高级特性。关键在于嵌套函数引用自由变量返回函数,并注意使用 nonlocal 来修改变量值。