Python 闭包的使用方法


Posted in Python onSeptember 07, 2017

Python 闭包的使用方法

嵌套函数中的非局部变量

在进入闭包之前,我们必须先了解一个嵌套函数和非局部变量。

在函数中定义另一个函数称为嵌套函数。嵌套函数可以访问包围范围内的变量。

在Python中,这些非局部变量只能在默认情况下读取,我们必须将它们显式地声明为非局部变量(使用nonlocal关键字)才能进行修改。

以下是访问非局部变量的嵌套函数的示例。

def print_msg(msg):
# This is the outer enclosing function

  def printer():
# This is the nested function
    print(msg)

  printer()

# We execute the function
# Output: Hello
print_msg("Hello")

可以看到嵌套函数printer()能够访问封闭函数的非局部变量msg。

定义闭包函数

在上面的例子中,如果函数print_msg()的最后一行返回printer()函数而不是调用它,会发生什么? 如该函数定义如下 -

def print_msg(msg):
# This is the outer enclosing function

  def printer():
# This is the nested function
    print(msg)

  return printer # this got changed

# Now let's try calling this function.
# Output: Hello
another = print_msg("Hello")
another()

这样是不寻常的。

print_msg()函数使用字符串“Hello”进行调用,返回的函数被绑定到另一个名称。 在调用another()时,尽管我们已经完成了print_msg()函数的执行,但仍然记住了这个消息。

一些数据(“Hello”)附加到代码中的这种技术在Python中称为闭包。

即使变量超出范围或函数本身从当前命名空间中删除,也会记住封闭范围内的值。

尝试在Python shell中运行以下内容以查看输出。

>>> del print_msg
>>> another()
Hello
>>> print_msg("Hello")
Traceback (most recent call last):
...
NameError: name 'print_msg' is not defined

什么时候闭包?

从上面的例子可以看出,当嵌套函数引用其封闭范围内的值时,在Python中有使用了一个闭包。

在Python中创建闭包必须满足的标准将在以下几点 -

  • 必须有一个嵌套函数(函数内部的函数)。
  • 嵌套函数必须引用封闭函数中定义的值。
  • 闭包函数必须返回嵌套函数。

何时使用闭包?

那么闭包是什么好的?

闭包可以避免使用全局值并提供某种形式的数据隐藏。它还可以提供面向对象的解决问题的解决方案。

当在类中几乎没有方法(大多数情况下是一种方法)时,闭包可以提供一个替代的和更优雅的解决方案。 但是当属性和方法的数量变大时,更好地实现一个类。

这是一个简单的例子,其中闭包可能比定义类和创建对象更为优先。

def make_multiplier_of(n):
  def multiplier(x):
    return x * n
  return multiplier

# Multiplier of 3
times3 = make_multiplier_of(3)

# Multiplier of 5
times5 = make_multiplier_of(5)

# Output: 27
print(times3(9))

# Output: 15
print(times5(3))

# Output: 30
print(times5(times3(2)))

Python中的装饰器也可以广泛使用闭包。值得注意的是,可以找到封闭函数中包含的值。

所有函数对象都有一个__closure__属性,如果它是一个闭包函数,它返回一个单元格对象的元组。 参考上面的例子,我们知道times3和times5是闭包函数。

>>> make_multiplier_of.__closure__
>>> times3.__closure__
(<cell at 0x0000000002D155B8: int object at 0x000000001E39B6E0>,)

单元格(cell)对象具有存储闭合值的属性:cell_contents。

>>> times3.__closure__[0].cell_contents
3
>>> times5.__closure__[0].cell_contents
5

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Python 相关文章推荐
Python 编码处理-str与Unicode的区别
Sep 06 Python
Python列表推导式、字典推导式与集合推导式用法实例分析
Feb 07 Python
python如何将图片转换为字符图片
Aug 19 Python
Python爬虫框架Scrapy基本用法入门教程
Jul 26 Python
python 多线程对post请求服务器测试并发的方法
Jun 13 Python
pyQT5 实现窗体之间传值的示例
Jun 20 Python
pandas 缺失值与空值处理的实现方法
Oct 12 Python
在tensorflow中设置保存checkpoint的最大数量实例
Jan 21 Python
新手学习Python2和Python3中print不同的用法
Jun 09 Python
Python  word实现读取及导出代码解析
Jul 09 Python
python实现KNN近邻算法
Dec 30 Python
教你如何使用Python实现二叉树结构及三种遍历
Jun 18 Python
Python基于回溯法子集树模板解决选排问题示例
Sep 07 #Python
Python基于回溯法子集树模板解决全排列问题示例
Sep 07 #Python
python中利用await关键字如何等待Future对象完成详解
Sep 07 #Python
Python基于回溯法子集树模板解决m着色问题示例
Sep 07 #Python
python中利用Future对象异步返回结果示例代码
Sep 07 #Python
python中利用Future对象回调别的函数示例代码
Sep 07 #Python
Python标准库之itertools库的使用方法
Sep 07 #Python
You might like
简单的PHP留言本实例代码
2010/05/09 PHP
Prototype使用指南之form.js
2007/01/10 Javascript
input、button的不同type值在ajax提交表单时导致的陷阱
2009/02/24 Javascript
IE6背景图片不缓存问题解决方案及图片使用策略多个方法小结
2012/05/14 Javascript
Extjs中的GridPanel隐藏列会显示在menuDisabled中解决方法
2013/01/27 Javascript
window.location的重写及判断location是否被重写
2014/09/04 Javascript
kindeditor修复会替换script内容的问题
2015/04/03 Javascript
JavaScript中Date对象的常用方法示例
2015/10/24 Javascript
node.js路径处理方法以及绝对路径详解
2021/03/04 Javascript
Bootstrap fileinput文件上传预览插件使用详解
2017/05/16 Javascript
vue.js+Echarts开发图表放大缩小功能实例
2017/06/09 Javascript
Nodejs之http的表单提交
2017/07/07 NodeJs
vue如何使用 Slot 分发内容实例详解
2017/09/05 Javascript
js + css实现标签内容切换功能(实例讲解)
2017/10/09 Javascript
vue中keep-alive的用法及问题描述
2018/05/15 Javascript
vue.js使用v-if实现显示与隐藏功能示例
2018/07/06 Javascript
python从入门到精通(DAY 2)
2015/12/20 Python
解决Python requests 报错方法集锦
2017/03/19 Python
Python基础练习之用户登录实现代码分享
2017/11/08 Python
python决策树之CART分类回归树详解
2017/12/20 Python
Python反射的用法实例分析
2018/02/11 Python
Python 使用PIL中的resize进行缩放的实例讲解
2018/08/03 Python
python实现梯度下降算法
2020/03/24 Python
python防止随意修改类属性的实现方法
2019/08/21 Python
Django之PopUp的具体实现方法
2019/08/31 Python
Python日志器使用方法及原理解析
2020/09/27 Python
canvas实现按住鼠标移动绘制出轨迹的示例代码
2018/02/05 HTML / CSS
美国高档百货Nordstrom的折扣店:Nordstrom Rack
2017/11/13 全球购物
Nicole Miller官方网站:纽约女装品牌
2019/09/14 全球购物
英语翻译系毕业生求职信
2013/09/29 职场文书
高级电工工作职责
2013/11/21 职场文书
保安公司服务承诺书
2014/05/28 职场文书
2014年护士长工作总结
2014/11/11 职场文书
小学思品教学反思
2016/02/20 职场文书
MySQL8.0无法启动3534的解决方法
2021/06/03 MySQL
利用python做数据拟合详情
2021/11/17 Python