python中什么是闭包?

*Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西。

闭包的概念

我们尝试从概念上去理解一下闭包。

在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。闭包可以用来在一个函数与一组“私有”变量之间创建关联关系。在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。

用比较容易懂的人话说,就是当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。看例子。

def make_printer(msg):

def printer():

print msg # 夹带私货(外部变量)

return printer # 返回的是函数,带私货的函数

printer = make_printer('Foo!')

printer()

支持将函数当成对象使用的编程语言,一般都支持闭包。比如Python, JavaScript。

如何理解闭包

闭包存在有什么意义呢?为什么需要闭包?

我个人认为,闭包存在的意义就是它夹带了外部变量(私货),如果它不夹带私货,它和普通的函数就没有任何区别。同一个的函数夹带了不同的私货,就实现了不同的功能。其实你也可以这么理解,闭包和面向接口编程的概念很像,可以把闭包理解成轻量级的接口封装。

接口定义了一套对方法签名的约束规则。

def tag(tag_name):

def add_tag(content):

return "{1}{0}>".format(tag_name, content)

return add_tag

content = 'Hello'

add_tag = tag('a')print add_tag(content)#Hello

add_tag = tag('b')print add_tag(content)#Hello

在这个例子里,我们想要一个给content加tag的功能,但是具体的tag_name是什么样子的要根据实际需求来定,对外部调用的接口已经确定,就是add_tag(content)。如果按照面向接口方式实现,我们会先把add_tag写成接口,指定其参数和返回类型,然后分别去实现a和b的add_tag。

但是在闭包的概念中,add_tag就是一个函数,它需要tag_name和content两个参数,只不过tag_name这个参数是打包带走的。所以一开始时就可以告诉我怎么打包,然后带走就行。

上面的例子不太生动,其实在我们生活和工作中,闭包的概念也很常见。比如说手机拨号,你只关心电话打给谁,而不会去纠结每个品牌的手机是怎么实现的,用到了哪些模块。再比如去餐馆吃饭,你只要付钱就可以享受到服务,你并不知道那桌饭菜用了多少地沟油。这些都可以看成闭包,返回来的是一些功能或者服务(打电话,用餐),但是这些功能使用了外部变量(天线,地沟油等等)。

你也可以把一个类实例看成闭包,当你在构造这个类时,使用了不同的参数,这些参数就是闭包里的包,这个类对外提供的方法就是闭包的功能。但是类远远大于闭包,因为闭包只是一个可以执行的函数,但是类实例则有可能提供很多方法。

何时使用闭包

其实闭包在Python中很常见,只不过你没特别注意这就是一个闭包。比如Python中的装饰器Decorator,假如你需要写一个带参数的装饰器,那么一般都会生成闭包。

为什么?因为Python的装饰器是一个固定的函数接口形式。它要求你的装饰器函数(或装饰器类)必须接受一个函数并返回一个函数:

# how to definedef wrapper(func1): # 接受一个callable对象

return func2 # 返回一个对象,一般为函数

#how to usedef target_func(args): # 目标函数

pass# 调用方式一,直接包裹

result = wrapper(target_func)(args)

# 调用方式二,使用@语法,等同于方式一@wrapperdef target_func(args):

pass

result = target_func()

那么如果你的装饰器如果带参数呢?那么你就需要在原来的装饰器上再包一层,用于接收这些参数。这些参数(私货)传递到内层的装饰器里后,闭包就形成了。所以说当你的装饰器需要自定义参数时,一般都会形成闭包。(类装饰器例外)

def html_tags(tag_name):

def wrapper_(func):

def wrapper(*args, **kwargs):

content = func(*args, **kwargs)

return "{content}{tag}>".format(tag=tag_name,content=content)

return wrapper

return wrapper_

@html_tags('b')def hello(name='Toby'):

return 'Hello {}!'.format(name)

# 不用@的写法如下# hello = html_tag('b')(hello)# html_tag('b') 是一个闭包,它接受一个函数,并返回一个函数print hello() # Hello Toby!printhello('world') # Helloworld!

关于装饰器的更深入剖析,可以看我写的另外一篇博客。

再深入一点

其实也不必太深入,理解这上面的概念,很多看起来头疼的代码也不过如此。

下面让我们来了解一下闭包的包到底长什么样子。其实闭包函数相对与普通函数会多出一个__closure__的属性,里面定义了一个元组用于存放所有的cell对象,每个cell对象一一保存了这个闭包中所有的外部变量。

>>> def make_printer(msg1, msg2):

def printer():

print msg1, msg2

return printer>>> printer = make_printer('Foo', 'Bar') # 形成闭包>>> printer.__closure__ # 返回cell元组

(, )

>>> printer.__closure__[0].cell_contents # 第一个外部变量'Foo'>>> printer.__closure__[1].cell_contents # 第二个外部变量'Bar'

python迭代是什么意思_python中什么是迭代?相关推荐

  1. python 可迭代对象是什么_python中可迭代对象指的是什么

    python中可迭代对象指的是什么 发布时间:2020-07-20 11:19:38 来源:亿速云 阅读:91 作者:清晨 小编给大家分享一下python中可迭代对象指的是什么,相信大部分人都还不怎么 ...

  2. python中迭代对象是什么_python中的迭代对象和迭代器

    一.什么是可迭代对象? 迭代是访问集合元素的一种方式.以直接作用于 for 循环的数据类型有以下几种:集合数据类型,如 list . tuple . dict . set . str 等: gener ...

  3. python常用函数的用法_python中常用函数整理

    1.map map是python内置的高阶函数,它接收一个函数和一个列表,函数依次作用在列表的每个元素上,返回一个可迭代map对象. class map(object):""&qu ...

  4. python匿名函数的作用_Python中的匿名函数及递归思想简析

    匿名函数 前言 上次咱们基本说了一下函数的定义及简单使用,Python中的基本函数及其常用用法简析,现在咱们整点进阶一些的.同样都是小白,咱也不知道实际需要不,但是对于函数的执行顺序以及装饰器的理解还 ...

  5. python里的join方法_python中join()方法介绍

    描述 Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串. 语法 join()方法语法: str . join ( sequence ) 参数 sequence -- ...

  6. python怎么用第三方库_python中第三方库的下载方法

    1.最常用:在命令行中输入  pip install "库名称"  例如 pip install gensim 查看pip的命令集: pip uninstall "库名& ...

  7. python新式类c3算法_python中的MRO和C3算法

    一. 经典类和新式类 1.python多继承 在继承关系中,python子类自动用友父类中除了私有属性外的其他所有内容.python支持多继承.一个类可以拥有多个父类 2.python2和python ...

  8. python下载哪一个安装包_python中正确安装对应版本的包

    python在写机器学习的代码过程中,需要引入如numpy.matpoltlib.pandas等等等.有时候直接pip install+对应的包名并不能正确安装,或者安装后依旧会出现安装不完全的情况. ...

  9. python购物车结算不了_python中购物车

    python的基础语法 python数据类型:(按特征划分) 数字类型: 1.整形:布尔形.长整型L.标准整形 2.非整形:双精度型.复数.decimal(不是内建类型) 序列类型: 1.字符串(st ...

最新文章

  1. mysql计算两gps坐标的距离_mysql 计算两坐标间的距离
  2. vimproc_mac.so” is not found
  3. linux删除最后一个字符串,Bash删除字符串中的第一个和最后一个字符
  4. 2019\National _C_C++_C\试题 B: 递增序列
  5. 切片slice(python)
  6. python3进阶_Python3 进阶教程 2020全新版
  7. BZOJ4681 [jsoi2010]旅行
  8. 图片区域帧差法识别物体_matlab
  9. 谈判失败:Oracle 杀死 Java EE
  10. android makefile文件批量拷贝文件的方法
  11. 7-1 是否同一棵二叉搜索树 (25 分)
  12. GO 计算所有并发任务的总时间 WaitGroup
  13. linux下cmake安装配置
  14. c语言程序流程图怎么写,C语言课程设计————写下流程图! 谢谢
  15. 二、appium的原理
  16. 计算机网络中的冗余的意思,计算机网络基础 实验四 交换网络中冗余链路.ppt
  17. 手机访问电脑虚拟服务器,User Agent Switcher插件使用教程【电脑模拟手机访问网站】...
  18. word写论文公式编号问题
  19. 添加打印机,错误为0x0000011b
  20. 一些高薪职位的能力需求。

热门文章

  1. 多案分库分表带来的问题-跨库关联查询
  2. Java领域的对象如何传输-基于 socket 进行对象传输
  3. reportInterruptAfterWait
  4. MyBatis开发步骤
  5. SpringMVC的请求-文件上传-文件上传的原理
  6. AOP日志-域对象创建与基本操作介绍
  7. 权限操作-springSecurity快速入门
  8. InputStreamReader介绍代码实现
  9. Zuul:路由转发,排除和自定义
  10. 数字证书 - Java加密与安全