当前位置: 首页 > news >正文

__closure__:闭包的“身份证”

要理解“闭包函数和嵌套函数的区别在于 __closure__ 属性”,首先需要明确 嵌套函数闭包函数 的基础关系——闭包函数是“满足特定条件的嵌套函数”,而 __closure__ 属性正是闭包函数区别于普通嵌套函数的“标志性特征”,它记录了闭包对外部变量的“捕获痕迹”。下面分步骤拆解这句话的含义:

第一步:先理清两个基础概念

在讲 __closure__ 之前,必须先明确“嵌套函数”和“闭包函数”的关系,避免混淆:

1. 嵌套函数(Nested Function)

在一个函数内部定义的函数,它是“函数嵌套”这一语法结构的统称,不强调是否引用外部变量。
例如,下面的 inner_func 就是一个嵌套函数,但它没有引用外部函数的变量,因此不是闭包:

def outer_func():# 内部定义的嵌套函数def inner_func():print("我是嵌套函数,没引用外部变量")return inner_func  # 返回嵌套函数# 调用外部函数,得到嵌套函数
func = outer_func()
func()  # 输出:我是嵌套函数,没引用外部变量

2. 闭包函数(Closure Function)

满足两个条件的嵌套函数

  • 条件1:嵌套在另一个函数(外部函数)内部;
  • 条件2:引用了外部函数的局部变量(即“捕获”了外部变量),且外部函数执行结束后,这些变量仍能被内层函数访问。

例如,下面的 inner_func 引用了外部函数的 x,因此是闭包函数:

def outer_func(x):# 嵌套函数,引用了外部变量 xdef inner_func(y):return x + y  # 引用外部函数的局部变量 xreturn inner_func  # 返回嵌套函数(此时它是闭包)# 外部函数执行结束,返回闭包函数
add5 = outer_func(5)
# 调用闭包时,仍能访问外部函数的 x=5
print(add5(3))  # 输出 8(5+3)

第二步:__closure__ 属性——闭包的“身份标识”

普通嵌套函数(未引用外部变量)和闭包函数(引用了外部变量)的核心区别,体现在 __closure__ 属性上:

  • 普通嵌套函数:没有 __closure__ 属性(或 __closure__None),因为它没有引用外部变量,无需“保留”外部变量;
  • 闭包函数:有 __closure__ 属性,其值是一个 元组,元组中的每一项都是一个 cell(“单元格”)对象——每个 cell 对应闭包引用的一个外部变量。

示例:对比普通嵌套函数和闭包的 __closure__

# 1. 普通嵌套函数(无外部变量引用)
def outer1():def inner1():print("普通嵌套函数")print("inner1 的 __closure__:", inner1.__closure__)  # 查看 __closure__return inner1# 2. 闭包函数(引用外部变量)
def outer2(x):def inner2(y):return x + y  # 引用外部变量 xprint("inner2 的 __closure__:", inner2.__closure__)  # 查看 __closure__return inner2# 测试普通嵌套函数
inner1 = outer1()
# 输出:inner1 的 __closure__: None(无外部变量引用)# 测试闭包函数
inner2 = outer2(5)
# 输出:inner2 的 __closure__: (<cell at 0x0000023...: int object at 0x...>,)
# 元组中有1个 cell 对象,对应引用的外部变量 x

第三步:cell_contents——读取闭包捕获的外部变量

__closure__ 元组中的每个 cell 对象,都有一个 cell_contents 属性,用于 获取该 cell 对应的外部变量的值

这解释了“闭包能在外部函数结束后仍访问外部变量”的原理:闭包通过 __closure__ 中的 cell 对象,“保留”了对外部变量的引用,而 cell_contents 就是访问这些变量的“入口”。

示例:用 cell_contents 查看闭包捕获的变量

def outer(x, y):# 闭包引用了外部变量 x 和 ydef inner(z):return x + y + zreturn inner# 外部函数执行,传入 x=2, y=3,返回闭包
closure = outer(2, 3)# 1. 查看 __closure__:元组有2个 cell(对应 x 和 y)
print("closure.__closure__:", closure.__closure__)
# 输出:(<cell at 0x0000023...: int object at 0x...>, <cell at 0x0000023...: int object at 0x...>)# 2. 用 cell_contents 读取每个外部变量的值
print("第一个 cell 的值(x):", closure.__closure__[0].cell_contents)  # 输出 2
print("第二个 cell 的值(y):", closure.__closure__[1].cell_contents)  # 输出 3# 3. 调用闭包,验证变量确实被保留
print(closure(4))  # 输出 9(2+3+4)

第四步:总结核心区别

通过 __closure__ 属性,我们能清晰区分“普通嵌套函数”和“闭包函数”:

特征 普通嵌套函数(未引用外部变量) 闭包函数(引用外部变量)
__closure__ 属性 None(无此属性或值为 None) 非 None 的元组,存储 cell 对象
cell 对象与 cell_contents 元组中每个 cell 对应一个捕获的外部变量,cell_contents 可读取变量值
外部变量的生命周期 外部函数执行结束后,变量被销毁 外部函数结束后,变量通过 cell 被保留,闭包可继续访问

简单来说:
__closure__ 是闭包的“身份证”——普通嵌套函数没有这张“身份证”(__closure__=None),而闭包函数通过这张“身份证”(__closure__ 元组)记录了它“带走”的外部变量,cell_contents 则是查看这些“带走的变量”的窗口。这也是闭包能突破“函数执行完局部变量销毁”常规的关键技术细节。

http://www.sczhlp.com/news/183477/

相关文章:

  • Codeforces 2153D Not Alone 题解 [ 绿 ] [ 线性 DP ] [ 分类讨论 ]
  • 南宁企业建站系统wordpress修改登录密码
  • 手机零售网站 关键词自己小程序制作流程
  • 客户说做网站没效果中山网站建设价格低
  • 无锡做网站优化公司可以用来做视频网站的视频外链吗
  • 临沂网站建设吧注册安全工程师报名条件和要求
  • 网站域名跳转代码龙华网站制作公司
  • 西部网站管理助手 伪静态网页回合制游戏排行榜
  • 广西网站设计公司企业站手机网站
  • 网站建设仟首先金手指12python自学视频教程
  • 网站建设贰金手指下拉壹玖建网站用
  • 做网站官网需多少钱网站建设 招标任务书
  • 手机网站 备案为什么网站浏览不是做的那样
  • 江西城乡建设厅网站毕节市生态文明建设网站
  • dede移动端网站源码外包网站设计哪家好
  • 网站建设的总体目标是什么智慧软文
  • 中山网站制作定制h5网站开发设计
  • 网站页面布局模板研发工程师和开发工程师
  • 株洲网站建设服务公司整合营销策略有哪些
  • 饿了么网站做生鲜吗教育网站制作要多少钱
  • 网站维护运营wordpress知识管理
  • 企业建站官网dz旅游网站模板
  • 网站流量一直下降管理系统首页
  • 湖州做网站公司网站拓展关键词怎么做
  • 洛阳网站搭建石家庄房产信息网
  • 做php网站教程视频教程东莞企业网站开发
  • 每日一题 ###121买卖股票的最佳时机
  • 10.10总结
  • LibreChat-图文并茂手把手教你界面配置 | Adorable LibreChat Interface Configuration Guide
  • Codeforces Round 1057 (Div. 2)