背景

本文尝试介绍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的元组。以上述示例进行说明,其中times3times5都是闭包函数,打印输出:

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)相关推荐

  1. Python 中的闭包、匿名函数、decorator 装饰器与python的偏函数

    Python中的闭包 def calc_sum(lst):def lazy_sum():return sum(lst)return lazy_sum 像这种内层函数引用了外层函数的变量(参数也算变量) ...

  2. python闭包的应用场景_简单谈谈Python中的闭包

    Python中的闭包 前几天又有人留言,关于其中一个闭包和re.sub的使用不太清楚.我在脚本之家搜索了下,发现没有写过闭包相关的东西,所以决定总结一下,完善Python的内容. 1. 闭包的概念 首 ...

  3. 什么是闭包及Python中的闭包

    什么是闭包 Objects are data with methods attached. Closures are functions with data attached. 一般来说,我们都非常熟 ...

  4. python代码:闭包closure的一个例子

    python代码:闭包closure的一个例子 #!/usr/bin/python # -*- coding: UTF-8 -*- """ @author: @file: ...

  5. Python中的闭包

    (如转载,请注明出处,谢谢.) 闭包这个概念在很多语言中都有涉及,本文主要谈谈python中的闭包.Python中使用闭包主要是在进行函数式开发时使用. 一,定义 python中的闭包从表现形式上定义 ...

  6. Python 中的闭包介绍

    引言 闭包是优雅的 Python 结构.在本文中,我们将了解它们,如何定义闭包,为什么以及何时使用它们. 但是在讨论什么是闭包之前,我们必须首先理解什么是嵌套函数,以及作用域规则是如何为它们工作的.那 ...

  7. Python中的闭包总结

    前几天又有人在我的这篇文章 python项目练习一:即时标记 下留言,关于其中一个闭包和re.sub的使用不太清楚.我在自己的博客上搜索了下,发现没有写过闭包相关的东西,所以决定总结一下,完善博客上P ...

  8. python有什么作用-Python中的闭包到底有什么用

    1.global关键字的作用 如果在函数中需要修改全局变量,则需要使用该关键字,具体参见下面例子. variable=100 deffunction():print(variable) #在函数内不对 ...

  9. javascript中的闭包closure详解

    文章目录 简介 函数中的函数 Closure闭包 使用闭包实现private方法 闭包的Scope Chain 闭包常见的问题 闭包性能的问题 总结 简介 闭包closure是javascript中一 ...

最新文章

  1. spring-java.lang.stackOverFlowError
  2. Python中dict用法详解
  3. 在Win7上安装WINDRIVER.TORNADO.V2.2.FOR.PENTIUM与运行HelloWorld
  4. AI基础:Python开发环境设置和小技巧
  5. HTML设置字体颜色1008无标题,如何在HTML中设置字体颜色,你知道这几种方式吗?...
  6. leetcode1085. 最小元素各数位之和 py不止是字符串的神!
  7. 存储过程编写经验和优化措施 1
  8. Redhat或者Centos手动安装Vim,
  9. 一文了解十大 Java 开发者必备测试框架!
  10. php伪静态规则生成,SEO工具箱:PHP自动生成PHPCMS伪静态规则.htaccess
  11. 常用的正则表达式,妈妈再也不用担心我不会写正则表达式了
  12. 基于BP神经网络和ORL库的人脸识别matlab仿真
  13. 汇川plc c语言,汇川plc可编程控制器模块种类
  14. 方舟生存进化服务器怎么开?方舟生存进化架设服务器教程
  15. 步进电机和伺服驱动器接线
  16. SWF怎么转FLV格式?
  17. 在香港用什么软件可以唱歌?香港K歌app推荐
  18. 一步一步建立自己的神经网络
  19. 使用BeautifulSoup,解释器报错‘lxml‘
  20. cad模型轻量化_【技术帖】基于轻量化概念的碳纤维复合材料汽车保险杠设计

热门文章

  1. DELPHI中鼠标的各种操作
  2. 电子货架标签-----智能基站V3
  3. 干货实操:微服务Spring Cloud 系列(二) Eureka服务发现与服务注册(strand alone)
  4. 一文弄懂Flink基础理论
  5. uniapp抖音网页版
  6. 机器学习中的特征是什么?机器学习知识点详解
  7. 计算机休眠变关机,电脑如何按关机键变成休眠
  8. 飞思卡尔K22调试FXOS8700加速度和电子罗盘
  9. 信息化时代的步伐题解
  10. catia 草图设计