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

python闭包满足的三个条件_Python中的闭包

闭包是什么

使用像javascript和python这样支持面向对象范式的语言进行编程时,都会涉及到闭包的概念以及闭包的使用。我们今天就从这两个方面来讨论一下闭包(本文仅针对python3):

首先是维基百科中关于闭包的概念:

在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。闭包可以用来在一个函数与一组“私有”变量之间创建关联关系。在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。

根据这句话,其实我们自己就可以总结出在python语言中形成闭包的三个条件,缺一不可:

1)必须有一个内嵌函数(函数里定义的函数)——这对应函数之间的嵌套

2)内嵌函数必须引用一个定义在闭合范围内(外部函数里)的变量——内部函数引用外部变量

3)外部函数必须返回内嵌函数——必须返回那个内部函数

前两个条件我们比较好理解,那什么会有第三条规定呢?其实闭包一词指的就是上文中提到的那个“内部的函数”,我们下面就会发现,只有那个内部函数才有所谓的__closure__属性。

我们首先来创造一个闭包:

def funx():

x=5

def funy():

nonlocal x

x+=1

return x

return funy

我们根据上面的三准则创造了一个函数,其中的funy就是所谓的闭包,而funy内部所引用过的x就是所谓的闭包变量。

闭包有什么用

我们在交互式模式下,对上面的函数进行简单的测试:

>>> a=funx()

>>> a()

6

>>> a()

7

>>> a()

8

>>> a()

9

>>> x

Traceback (most recent call last):

File "", line 1, in

x

NameError: name 'x' is not defined

>>>

我们会发现,funx中的x变量原本仅仅是funx的一个局部变量。但是形成了闭包之后,它的行为就好像是一个全局变量一样。但是最后的错误说明x并不是一个全局变量。其实这就是闭包的一个十分浅显的作用,形成闭包之后,闭包变量能够随着闭包函数的调用而实时更新,就好像是一个全局变量那样。(注意我们上面的a=funx(),a实际上应该是funy,所以a称为闭包)

进一步探究

我们能否找出点证据证明我们对于闭包的猜想呢?很简单,我们可以尝试下面的操作:

>>> a.__closure__

(,)

>>> type(a.__closure__)

>>> type(a.__closure__[0])

>>> a.__closure__[0].cell_contents

9

>>> a()

10

>>> a.__closure__[0].cell_contents

10

>>> def test():pass

>>> test.__closure__==None

True

>>>

这样我们就明白了,形成闭包之后,闭包函数会获得一个非空的__closure__属性(对比我们最后的函数test,test是一个不具备闭包的函数,它的__closure__属性是None),这个属性是一个元组。元组里面的对象为cell对象,而访问cell对象的cell_contents属性则可以得到闭包变量的当前值(即上一次调用之后的值)。而随着闭包的继续调用,变量会再次更新。所以可见,一旦形成闭包之后,python确实会将__closure__和闭包函数绑定作为储存闭包变量的场所。

相关文章:

  • javascript等待异步线程完成_程序员修神之路--问世间异步为何物?
  • python取随机数画图_python3测试工具开发快速入门教程1turtle绘图-4选择与随机数...
  • python中如何输入多行字符_python中怎么输入多行字符串
  • python饼图显示百分比_解决echarts饼图显示百分比,和显示内容字体及大小
  • java 二维数组定义长方体_47.二维数组的定义
  • zap 自定义日志格式_Go 每日一库之 zap
  • python接管已经打开ie浏览器_Python Webdriver 重新使用已经打开的浏览器实例
  • python 单例 多线程_python 单例模式
  • echarts绘制大数量折线图导致浏览器崩溃_现代浏览器内部机制
  • filestream读取文件_ASP.NET Core WebAPI文件下载
  • python怎么循环合并数组_python数组循环合并python执行系统命令四种方法比较
  • git pull 强制覆盖本地_用git简单粗暴地完成本地、服务器同步
  • github可视化工具_深度学习训练过程可视化(附github源码)
  • grep 与条件_【125】Linux 中 ps ef|grep和ps、grep详解
  • linux搜索文件_学习+使用Linux的最佳姿势,收录近600条Linux系统命令
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • angular2 简述
  • pdf文件如何在线转换为jpg图片
  • text-decoration与color属性
  • 翻译--Thinking in React
  • 前端代码风格自动化系列(二)之Commitlint
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 浅谈web中前端模板引擎的使用
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 小试R空间处理新库sf
  • 源码安装memcached和php memcache扩展
  • 走向全栈之MongoDB的使用
  • ​Spring Boot 分片上传文件
  • ​水经微图Web1.5.0版即将上线
  • # include “ “ 和 # include < >两者的区别
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • #微信小程序(布局、渲染层基础知识)
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (笔试题)合法字符串
  • (二)换源+apt-get基础配置+搜狗拼音
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • ***详解账号泄露:全球约1亿用户已泄露
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NET Core 版本不支持的问题
  • .NET Core 中插件式开发实现
  • .Net IOC框架入门之一 Unity
  • .NET大文件上传知识整理
  • .net反编译的九款神器
  • .NET文档生成工具ADB使用图文教程
  • @PreAuthorize注解
  • @test注解_Spring 自定义注解你了解过吗?
  • [ C++ ] template 模板进阶 (特化,分离编译)
  • [\u4e00-\u9fa5] //匹配中文字符
  • [C#]C# OpenVINO部署yolov8图像分类模型
  • [c#基础]值类型和引用类型的Equals,==的区别
  • [C#小技巧]如何捕捉上升沿和下降沿
  • [Everyday Mathematics]20150130
  • [HarekazeCTF2019]encode_and_encode 不会编程的崽
  • [Intel Edison开发板] 05、Edison开发基于MRAA实现IO控制,特别是UART通信