python中的闭包(closure)
背景
本文尝试介绍Python中的闭包(closure),包括闭包是什么? 为什么要使用闭包?如何使用闭包?
嵌套函数及非局部变量
在介绍闭包之前,需要先明白什么是嵌套函数和非局部变量。在一个函数(fun1)中定义的另一个函数(fun2)称为嵌套函数。嵌套函数(fun1)可以访问外围作用域的变量,即为非局部变量。换一句话说,嵌套函数能够访问enclosing scope(闭包作用域,或者外围作用域,或者外层作用域)下的变量。这些非局部变量默认情况下是只读的,为了修改它们,必须显式地将它们声明为非局部变量(使用nonlocal
关键字)。具体示例如下:
def print_msg(msg):# 这是外层函数def printer():# 这是嵌套函数print(msg)printer()# 调用外层函数print_msg("Hello World")
输出:
Hello World
可以看出,嵌套函数printer()
是可以访问到非局部变量msg
,即外层函数中的msg
。
定义一个闭包函数
如果上述示例print_msg()
函数的最后一行不是调用printer()
,而是返回printer
呢?具体代码改成如下:
def print_msg(msg):def printer():# 这是一个嵌套函数print(msg)return printer # 返回嵌套函数# Now let's try calling this function.# 输出: Hello Worldanother = print_msg("Hello World")another()
可以看出输出结果是:
Hello World
这里调用print_msg()
函数的时候传入了字符串Hello World
,返回函数名为another
。在调用another()
时,之前传入的字符串Hello World
信息仍然保留,尽管我们已经完成了print_msg()
函数的执行。
这种将一些数据(比如上述示例中的Hello World
)附加到代码中的技术在Python中称为闭包。enclosing scope中的值会被存储,即使该变量超出作用域,或者函数本身被从当前命名空间中删除,也会记住外围作用域中的这个值。比如:
del print_msg
another()
依然能够输出:
Hello World
此时尝试调用:
print_msg("Hello")
报错如下:
File "test.py", line 306, in <module>print_msg("Hello World")
NameError: name 'print_msg' is not defined
因为返回函数仍然可以正常工作,而原始的函数已经被删除,无法像之前那样起作用。
什么是闭包
正如上面的例子所示,当嵌套函数在其外围作用域中引用一个值时,就出现了一个闭包。在Python中创建闭包,须满足的条件总结如下:
- 必须有一个嵌套函数(函数中有函数)
- 嵌套函数必须引用外围函数中定义的值
- 外围函数必须返回嵌套函数
什么时候使用闭包
闭包可以避免使用全局变量,并提供某种形式的数据隐藏。它还可以为这个问题提供一个面向对象的解决方案。当类中需要实现的方法很少(大多数情况下只有一个方法)时,闭包可以提供一种替代的、更优雅的解决方案。但是,当属性和方法的数量比较多时,最好实现一个类。
下面是一个简单的例子,闭包可能比定义类和创建对象更合适。
def make_multiplier_of(n):def multiplier(x):return x * nreturn multiplier# Multiplier of 3
times3 = make_multiplier_of(3)# Multiplier of 5
times5 = make_multiplier_of(5)# 输出: 27
print(times3(9))# 输出: 15
print(times5(3))# 输出: 30
print(times5(times3(2)))
另外,需要注意的是:闭包函数中包含的值是可以找到的。所有的函数对象都有__closure__
属性。当是闭包函数时,该属性返回cell objects的元组。以上述示例进行说明,其中times3
和times5
都是闭包函数,打印输出:
print(make_multiplier_of.__closure__)
print(times3.__closure__)
输出结果如下:
None
(<cell at 0x7f5c8d8cb618: int object at 0xa68b00>,)
cell对象中的属性cell_contents
存储着闭包值:
print(times3.__closure__[0].cell_contents)
print(times5.__closure__[0].cell_contents)
输出结果如下:
3
5
python中的闭包(closure)相关推荐
- Python 中的闭包、匿名函数、decorator 装饰器与python的偏函数
Python中的闭包 def calc_sum(lst):def lazy_sum():return sum(lst)return lazy_sum 像这种内层函数引用了外层函数的变量(参数也算变量) ...
- python闭包的应用场景_简单谈谈Python中的闭包
Python中的闭包 前几天又有人留言,关于其中一个闭包和re.sub的使用不太清楚.我在脚本之家搜索了下,发现没有写过闭包相关的东西,所以决定总结一下,完善Python的内容. 1. 闭包的概念 首 ...
- 什么是闭包及Python中的闭包
什么是闭包 Objects are data with methods attached. Closures are functions with data attached. 一般来说,我们都非常熟 ...
- python代码:闭包closure的一个例子
python代码:闭包closure的一个例子 #!/usr/bin/python # -*- coding: UTF-8 -*- """ @author: @file: ...
- Python中的闭包
(如转载,请注明出处,谢谢.) 闭包这个概念在很多语言中都有涉及,本文主要谈谈python中的闭包.Python中使用闭包主要是在进行函数式开发时使用. 一,定义 python中的闭包从表现形式上定义 ...
- Python 中的闭包介绍
引言 闭包是优雅的 Python 结构.在本文中,我们将了解它们,如何定义闭包,为什么以及何时使用它们. 但是在讨论什么是闭包之前,我们必须首先理解什么是嵌套函数,以及作用域规则是如何为它们工作的.那 ...
- Python中的闭包总结
前几天又有人在我的这篇文章 python项目练习一:即时标记 下留言,关于其中一个闭包和re.sub的使用不太清楚.我在自己的博客上搜索了下,发现没有写过闭包相关的东西,所以决定总结一下,完善博客上P ...
- python有什么作用-Python中的闭包到底有什么用
1.global关键字的作用 如果在函数中需要修改全局变量,则需要使用该关键字,具体参见下面例子. variable=100 deffunction():print(variable) #在函数内不对 ...
- javascript中的闭包closure详解
文章目录 简介 函数中的函数 Closure闭包 使用闭包实现private方法 闭包的Scope Chain 闭包常见的问题 闭包性能的问题 总结 简介 闭包closure是javascript中一 ...
最新文章
- spring-java.lang.stackOverFlowError
- Python中dict用法详解
- 在Win7上安装WINDRIVER.TORNADO.V2.2.FOR.PENTIUM与运行HelloWorld
- AI基础:Python开发环境设置和小技巧
- HTML设置字体颜色1008无标题,如何在HTML中设置字体颜色,你知道这几种方式吗?...
- leetcode1085. 最小元素各数位之和 py不止是字符串的神!
- 存储过程编写经验和优化措施 1
- Redhat或者Centos手动安装Vim,
- 一文了解十大 Java 开发者必备测试框架!
- php伪静态规则生成,SEO工具箱:PHP自动生成PHPCMS伪静态规则.htaccess
- 常用的正则表达式,妈妈再也不用担心我不会写正则表达式了
- 基于BP神经网络和ORL库的人脸识别matlab仿真
- 汇川plc c语言,汇川plc可编程控制器模块种类
- 方舟生存进化服务器怎么开?方舟生存进化架设服务器教程
- 步进电机和伺服驱动器接线
- SWF怎么转FLV格式?
- 在香港用什么软件可以唱歌?香港K歌app推荐
- 一步一步建立自己的神经网络
- 使用BeautifulSoup,解释器报错‘lxml‘
- cad模型轻量化_【技术帖】基于轻量化概念的碳纤维复合材料汽车保险杠设计