浅显理解 Pyhton 中闭包

浅显理解 Pyhton 中闭包

什么是闭包? 闭包( Closure )是词法闭包( Lexical Closure )的简称。 闭包就是内层函数, 对外层函数(非全局)的变量的引用. 叫闭包

  • 可以保护我的变量
  • 闭包的作用就是让⼀一个变量能够常驻内存. 供后面的程序使用.
  • 简单示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #我们可以使⽤用 __closure__ 来检测函数是否是闭包. 使⽤用函数名 .__closure__ 返回 cell 就是闭包. 返回None就不是闭包

    def func1():
    name = "馒头"
    def func2():
    print(name) # 闭包
    func2()
    print(func2.__closure__) # (<cell at 0x10c2e20a8: str object at0x10c3fc650>,)
    func1()

    #调用内部函数
    def outer():
    name = "土豆"
    # 内部函数
    def inner():
    print(name)
    return inner
    fn = outer() # 访问外部函数, 获取到内部函数的函数地址
    fn() # 访问内部函数


    #多层嵌套呢
    def func1():
    def func2():
    def func3():
    print("嘿嘿")
    return func3
    return func2
    func1()()()
  • 应用 爬虫

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from urllib.request import urlopen
    def but():
    content = urlopen("http://www.mi.cn/index.html").read()
    def get_content():
    return content
    return get_content
    fn = but() # 这个时候就开始加载校花100的内容
    # 后⾯面需要⽤用到这⾥里里⾯面的内容就不不需要在执⾏行行⾮非常耗时的⽹网络连接操作了了
    content = fn() # 获取内容
    print(content)
    content2 = fn() # 重新获取内容
    print(content2)
  • 装饰器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # how to define
    def wrapper(func1): # 接受一个callable对象
    return func2 # 返回一个对象,一般为函数

    # how to use
    def target_func(args): # 目标函数
    pass

    # 调用方式一,直接包裹
    result = wrapper(target_func)(args)

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

    result = target_func()
  • __closure__ 属性和 cell 对象

    其实闭包函数相对与普通函数会多出一个 __closure__ 的属性,而 __closure__ 属性定义了 cell 对象的元祖 ,元祖中 保存了这个闭包中所有的 外部变量 。

    包含 __closure__ 属性 就是 闭包函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    def out(arg1, arg2):
    def inner():
    print(arg1,arg2)
    return inner
    ine = out('man','info')
    print(ine.__closure__) # 返回的是 cell 对象的元祖,其中元组中的每一个 cell 对象用来保存作用域中变量的值。
    print(ine.__closure__[0].cell_contents)
    print(type(ine.__closure__),type(ine.__closure__[0])) # 元祖, cell 对象组成的元祖
    print(type(ine.__closure__),type(ine.__closure__[1])) # 第二个外部变量
    print(ine)


    # 执行结果
    (<cell at 0x103596888: str object at 0x103561378>, <cell at 0x103596828: str object at 0x1034fc3b0>)
    man # 第一个外部变量
    info # 第二个外部变量
    <class 'tuple'> <class 'cell'>
    <function out.<locals>.inner at 0x10356cd08>

    最后:

    我们可以使⽤用__closure__来检测函数是否是闭包. 使⽤用函数名 .closure 返回 cell 就是闭包. 返回None就不是闭包


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!