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获取本机mac地址和ip地址的方法
Apr 29 Python
Python实现复杂对象转JSON的方法示例
Jun 22 Python
Python深度优先算法生成迷宫
Jan 22 Python
浅谈Python里面小数点精度的控制
Jul 16 Python
Python开发最牛逼的IDE——pycharm
Aug 01 Python
Python3实现的简单工资管理系统示例
Mar 12 Python
python实现维吉尼亚加密法
Mar 20 Python
python3+PyQt5 数据库编程--增删改实例
Jun 17 Python
python3.6连接mysql数据库及增删改查操作详解
Feb 10 Python
python图片剪裁代码(图片按四个点坐标剪裁)
Mar 10 Python
浅谈keras中的Merge层(实现层的相加、相减、相乘实例)
May 23 Python
matplotlib subplot绘制多个子图的方法示例
Jul 28 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
PHPCrawl爬虫库实现抓取酷狗歌单的方法示例
2017/12/21 PHP
PHP调用接口用post方法传送json数据的实例
2018/05/31 PHP
js监控IE火狐浏览器关闭、刷新、回退、前进事件
2014/07/23 Javascript
Jquery实现兼容各大浏览器的Enter回车切换输入焦点的方法
2014/09/01 Javascript
在父页面得到zTree已选中的节点的方法
2015/02/12 Javascript
javascript实现 百度翻译 可折叠的分享按钮列表
2015/03/12 Javascript
jQuery插件Elastislide实现响应式的焦点图无缝滚动切换特效
2015/04/12 Javascript
javascript实现全局匹配并替换的方法
2015/04/27 Javascript
jquery实现页面虚拟键盘特效
2015/08/08 Javascript
JQuery 两种方法解决刚创建的元素遍历不到的问题
2016/04/13 Javascript
第十章之巨幕页头缩略图与警告框组件
2016/04/25 Javascript
JS中script标签defer和async属性的区别详解
2016/08/12 Javascript
jquery validate表单验证插件
2016/09/06 Javascript
js正则表达式注册页面表单验证
2016/10/11 Javascript
JavaScript实现移动端轮播效果
2017/06/06 Javascript
Vue自定义指令实现checkbox全选功能的方法
2018/02/28 Javascript
jQuery实现table表格信息的展开和缩小功能示例
2018/07/21 jQuery
微信小程序之事件交互操作实例分析
2018/12/03 Javascript
js canvas实现星空连线背景特效
2019/11/01 Javascript
vue flex 布局实现div均分自动换行的示例代码
2020/08/05 Javascript
vue实现tab栏点击高亮效果
2020/08/19 Javascript
vue实现移动端返回顶部
2020/10/12 Javascript
Python的Tornado框架实现图片上传及图片大小修改功能
2016/06/30 Python
Python 描述符(Descriptor)入门
2016/11/20 Python
用python结合jieba和wordcloud实现词云效果
2017/09/05 Python
深入理解Django的中间件middleware
2018/03/14 Python
解决pytorch-yolov3 train 报错的问题
2020/02/18 Python
个人自我鉴定怎么写
2013/10/28 职场文书
会议开场欢迎词
2014/01/15 职场文书
回门宴父母答谢词
2014/01/26 职场文书
追悼会子女答谢词
2014/01/28 职场文书
领导失职检讨书
2014/02/24 职场文书
党员带头倡议书
2015/04/29 职场文书
Pytorch可视化的几种实现方法
2021/06/10 Python
Go归并排序算法的实现方法
2022/04/06 Golang
kubernetes集群搭建Zabbix监控平台的详细过程
2022/07/07 Servers