python闭包怎么理解_Python 闭包的理解

Last Updated on 2019年10月15日

Python中的闭包是一个比较模糊的概念,不太好理解,我最近的面试中也被问及,在一个单例模式的实现上,我用装饰器实现单例,然后面试官就问到了我对闭包的理解,回答的不太清楚。

所以,回来后,好好的查资料理解了一下闭包的概念。下面我们就一起来试着理解这个概念,这在对Python的不断学习中,也是一个避不开的概念。希望对大家有用。

闭包

首先,闭包并不只是一个python中的概念,在函数式编程语言中基本都有应用。

闭包是引用了自由变量的函数,这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。

所以简单的说,就是函数定义中引用了函数外定义的变量,并且该函数可以在其定义环境外被执行,相同的函数实例在执行中此外部定义的变量是共享的。然后此外部定义的变量又是外部函数的内部变量,外部函数返回此定义的内部函数,这样就形成了一个闭包。

看下面示例:

def a():

var = []

def b(para):

var.append(para)

print(var)

return b

s = a()

s(1)

s(2)

# 输出结果:

[1]

[1, 2]

[3]

[3, 4]

如上,可以看到,内部函数b应用了外部变量var,在函数b中修改外部变量var,并打印出来,然后外部函数返回此内部函数。

通过外部函数,生成内部函数实例s,运行s函数,会发现外部变量var的值是可以保存和共享的。但是我们再次生成新的函数实例s2,会发现s2中的var变量和s的是不相关的,此外部变量是跟函数实例相关的。

如此,基本可以得到:

闭包中的引用的自由变量只和具体的闭包有关联,闭包的每个实例引用的自由变量互不干扰。

一个闭包实例对其自由变量的修改会被传递到下一次该闭包实例的调用。

而创建一个闭包,基本也要满足以下几点:

必须有内嵌函数

内嵌函数必须引用外部变量

外部函数必须返回内嵌函数

到此, 你是不是发现这个跟什么很相似,是的,就是装饰器!

Python装饰器就是闭包概念的一种体现。

这也就解释了为什么面试官在看到我用装饰器实现单例的时候,会问我闭包。因为这就是很典型的闭包的,看下面单例模式的装饰器:

from functools import wraps

def Singleton(cls):

instance = {}

@wraps(cls)

def wrapper(*args, **kwargs):

if cls not in instance:

instance[cls] = cls(*args, **kwargs)

return instance[cls]

return wrapper

其中,外部变量instance就是被内部函数wrapper引用,外部函数最后返回内部函数,就是一个典型的闭包。每个被此装饰器装饰后的类,都会有一个独有的instance变量来保存实例,因为闭包中每个实例引用的自由变量instance互不干扰,所以能实现单例模式。

对单例模式不熟悉的,请看:《Python 单例模式》

OK,大致闭包的概念就是如此,理解闭包主要是要理解其中的设计思想,这样才能更好的使用闭包。

有任何问题,欢迎留言

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/541493.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java BufferedReader mark()方法与示例

BufferedReader类mark()方法 (BufferedReader Class mark() method) mark() method is available in java.io package. mark()方法在java.io包中可用。 mark() method is used to mark the current position in this stream and whenever we call reset() method so it will re…

《全球互联网金融商业模式:格局与发展》——第3章,第3节互联网保险公司...

本节书摘来自华章出版社《全球互联网金融商业模式:格局与发展》一书中的第3章,第3.3节互联网保险公司,作者廖理,更多章节内容可以访问云栖社区“华章计算机”公众号查看 3.3 互联网保险公司互联网思维贯穿整个保险创新发展过程&a…

webapi随机调用_BeetleX之webapi验证插件JWT集成

对于webapi服务应用很多时候需要制订访问限制,在前面的章节也讲述了组件如何制订控制器访问控制;但到了实际应用要自己去编写还是比较麻烦。为了让访问控制更方便组件实现基于JWT的控制器访问控制组件BeetleX.FastHttpApi.Jwt;通过这个组件可…

java bitset_Java BitSet nextClearBit()方法与示例

java bitsetBitSet类nextClearBit()方法 (BitSet Class nextClearBit() method) nextClearBit() method is available in java.util package. nextClearBit()方法在java.util包中可用。 nextClearBit() method is used to retrieve the index of the first bit that is set to …

《驯狮记——Mac OS X 10.8 Mountain Lion使用手册》——2.3 Dock

本节书摘来自异步社区《驯狮记——Mac OS X 10.8 Mountain Lion使用手册》一书中的第2章,第2.3节,作者:陈明 , 张铮 , 马玉龙著,更多章节内容可以访问云栖社区“异步社区”公众号查看 2.3 Dock 驯狮记——Mac OS X 10.8 Mountain…

mysql 嵌套if标签_对比Excel、MySQL、Python,分别讲述 “if函数” 的使用原理!

作者:黄伟呢本文转自:数据分析与统计学之美其实,不管是Excel、MySQL,还是Python,“if”条件判断都起着很重要的作用。今天这篇文章,就带着大家盘点一下,这三种语言如何分别使用 “if函数” 。if…

Java BigDecimal intValue()方法与示例

BigDecimal类的intValue()方法 (BigDecimal Class intValue() method) intValue() method is available in java.math package. intValue()方法在java.math包中可用。 intValue() method is used to convert a BigDecimal to an integer and when the converted BigDecimal val…

R语言数据挖掘

数据分析与决策技术丛书 R语言数据挖掘 Learning Data Mining with R [哈萨克斯坦]贝特麦克哈贝尔(Bater Makhabel) 著 李洪成 许金炜 段力辉 译 图书在版编目(CIP)数据 R语言数据挖掘 / (哈…

linux adduser mysql_linux_adduser

新帐号建立当不加-D参数,useradd指令使用命令列来指定新帐号的设定值and使用系统上的预设值.新使用者帐号将产生一些系统档案,使用者目录建立,拷备起始档案等,这些均可以利用命令列选项指定。此版本为RedHatLinux提供,可帮每个新加…

java iterator_Java ArrayDeque iterator()方法与示例

java iteratorArrayDeque类iterator()方法 (ArrayDeque Class iterator() method) iterator() Method is available in java.lang package. iterator()方法在java.lang包中可用。 iterator() Method is used to return an iterator over the deque elements. iterator()方法用于…

《jQuery、jQuery UI及jQuery Mobile技巧与示例》——7.4 示例:使用按钮集装饰单选框...

本节书摘来自异步社区《jQuery、jQuery UI及jQuery Mobile技巧与示例》一书中的第7章,第7.4节,作者:【荷】Adriaan de Jonge , 【美】Phil Dutson著,更多章节内容可以访问云栖社区“异步社区”公众号查看 7.4 示例:使…

mysql 模拟序列_【原创】MySQL 模拟PostgreSQL generate_series 表函数

PostgreSQL 提供了一个很强大的造数据的函数generate_series,基于Common Table Expression。MySQL 没有复杂的应用程序类型,该如何实现这样的功能呢? 我想到的三种方法如下:1. 用存储过程来做。 缺点是写好多数据库不擅长的应用逻辑。2. 我们…

Python字符串| isdigit()方法与示例

isdigit() is an in-built method in Python, which is used to check whether a string contains only digits or not. isdigit()是Python中的内置方法,用于检查字符串是否仅包含数字。 Digit value contains all decimal characters and other digits which may …

vue2.0的学习

vue-router 除了使用 <router-link> 创建 a 标签来定义导航链接&#xff0c;我们还可以借助 router 的实例方法&#xff0c;通过编写代码来实现。 1&#xff09;router.push(location) 这个方法会向 history 栈添加一个新的记录&#xff0c;所以&#xff0c;当用户点击浏…

mysql+url的配置参数详解_MySql链接url参数详解

mysql URL格式如下&#xff1a;jdbc:mysql://[host:port],[host:port].../[database][?参数名1][参数值1][&参数名2][参数值2]...MySQL在高版本需要指明是否进行SSL连接 在url后面加上 useSSLtrue 不然写程序会有warning常用的几个较为重要的参数&#xff1a;参数名…

Java LocalDate类| minus()方法与示例

LocalDate类isSupported()方法 (LocalDate Class isSupported() method) Syntax: 句法&#xff1a; public LocalDate minus(TemporalAmount t_amt);public LocalDate minus(long amt, TemporalUnit t_unit);isSupported() method is available in java.time package. isSuppo…

《Java EE 7精粹》—— 第3章 JSF 3.1 Facelets

本节书摘来异步社区《Java EE 7精粹》一书中的第2章&#xff0c;第2.1节&#xff0c;作者&#xff1a;【美】Arun Gupta&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看。 第3章 JSF JSF是基于Java的Web应用程序开发的服务器端用户界面&#xff08;UI&#xf…

mysql5批处理_转关于mysql5.5 的批处理讨论(转载)

MySql的JDBC驱动不支持批量操作(已结)MySql连接的url中要加rewriteBatchedStatements参数&#xff0c;例如String connectionUrl"jdbc:mysql://192.168.1.100:3306/test?rewriteBatchedStatementstrue";还要保证mysql JDBC驱的版本。MySql的JDBC驱动的批量插入操作性…

Java Duration类| isZero()方法与示例

持续时间类isZero()方法 (Duration Class isZero() method) isZero() method is available in java.time package. isZero()方法在java.time包中可用。 isZero() method is used to check whether this Duration object holds the value of length is 0 or not. isZero()方法用…

《C#多线程编程实战(原书第2版)》——3.2 在线程池中调用委托

本节书摘来自华章出版社《C#多线程编程实战&#xff08;原书第2版&#xff09;》一书中的第3章&#xff0c;第3.2节&#xff0c;作者&#xff08;美&#xff09;易格恩阿格佛温&#xff08;Eugene Agafonov&#xff09;&#xff0c;黄博文 黄辉兰 译&#xff0c;更多章节内容可…