python闭包的实例详解

 更新时间:2021年10月15日 08:33:39   作者:小妮浅浅  
在本篇文章里小编给大家整理的是一篇关于python闭包的实例详解内容,有兴趣的朋友们可以学习下。

1、在外部函数中定义内部函数,内部函数包含访问外部函数。即使外部函数的生命周期结束后,内部函数仍然可以访问外部函数变量。

2、外部函数的返回值是内部函数本身。

实例

def outer():
    cheer = 'hello '
    def inner(name):
        return cheer + name
    return inner
if __name__ == "__main__":
    #输出hello kevin
    print(outer()('kevin'))

知识点扩展:

闭包的概念

我们尝试从概念上去理解一下闭包。
在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部函数引用了外部函数的变量,则可能产生闭包。闭包可以用来在一个函数与一组“私有”变量之间创建关联关系。在给定函数被多次调用过程中,这些私有变量能够保持持久性。
用比较容易懂得人话说,就是当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。看下例子:

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 "<{0}>{1}</{0}>".format(tag_name, content)
  return add_tag
 
content = "Hello"
 
add_tag = tag('a')
print(add_tag(content)) # <a>Hello</a>
 
add_tag = tag('b')
print(add_tag(content)) # <b>Hello</b>

在这个例子里,我们想要给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 define
def wrapper(func1): # 接受一个callable对象
  return func1 # 返回一个对象,一般为函数
 
 
# how to use
def target_func(args): # 目标函数
  pass
 
 
# 调用方式1,直接包裹
result = wrapper(target_func("123"))
 
# 调用方式2,使用@语法,等同于方式1
@wrapper
def target_func(args):
  pass
 
result = target_func()

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

def html_tags(tag_name):
  def wrapper_(func):
    def wrapper(*args, **kwargs):
      content = func(*args, **kwargs)
      return "<{tag}>{content}</{tag}>".format(tag=tag_name, content=content)
    return wrapper
  return wrapper_
 
 
@html_tags('a')
def hello(name='Toby'):
  return "Hello {}!".format(name)
 
 
# 不用@的写法
# hello = html_tags('b')(hello)
# html_tags('b') 是一个闭包,它接受一个函数,并返回一个函数
 
print(hello()) # <a>Hello Toby!</a>
print(hello("world")) # <a>Hello world!</a>

到此这篇关于python闭包的实例详解的文章就介绍到这了,更多相关python闭包的特点内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python实现自动登录

    python实现自动登录

    这篇文章主要为大家详细介绍了python实现自动登录,填充网页表单,从而自动登录WEB门户,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-09-09
  • 详解用pyecharts Geo实现动态数据热力图城市找不到问题解决

    详解用pyecharts Geo实现动态数据热力图城市找不到问题解决

    这篇文章主要介绍了详解用pyecharts Geo实现动态数据热力图城市找不到问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-06-06
  • python list转置和前后反转的例子

    python list转置和前后反转的例子

    今天小编就为大家分享一篇python list转置和前后反转的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-08-08
  • python爬取网易云音乐排行榜实例代码

    python爬取网易云音乐排行榜实例代码

    大家好,本篇文章主要讲的是python爬取网易云音乐排行榜数据代码,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • python获取远程图片大小和尺寸的方法

    python获取远程图片大小和尺寸的方法

    这篇文章主要介绍了python获取远程图片大小和尺寸的方法,实例分析了Python中urllib2.urlopen方法及图片操作技巧,需要的朋友可以参考下
    2015-03-03
  • python数据结构之图深度优先和广度优先实例详解

    python数据结构之图深度优先和广度优先实例详解

    这篇文章主要介绍了python数据结构之图深度优先和广度优先,较为详细的分析了深度优先和广度优先算法的概念与原理,并给出了完整实现算法,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • 详解Python如何实现Excel数据读取和写入

    详解Python如何实现Excel数据读取和写入

    这篇文章主要为大家详细介绍了python如何实现对EXCEL数据进行读取和写入,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • python连接读写操作redis的完整代码实例

    python连接读写操作redis的完整代码实例

    这篇文章主要介绍了python连接读写操作redis的完整代码实例,包括redis连接与读写操作,redis-sentinel哨兵模式下Python操作redis,redis-cluster(集群)模式下Python操作redis,需要的朋友可以参考下
    2023-01-01
  • python 常用的基础函数

    python 常用的基础函数

    这篇文章主要介绍了python 77种常用的基础函数,学习python的朋友可以收藏一下,简单了解一下,方便后期使用
    2018-07-07
  • Python使用chardet判断字符编码

    Python使用chardet判断字符编码

    这篇文章主要介绍了Python使用chardet判断字符编码的方法,较为详细的分析了Python中chardet的功能、安装及使用技巧,需要的朋友可以参考下
    2015-05-05

最新评论