闭包

目录

    在嵌套函数内,使用非全局变量(且不是本层变量) -- 就是闭包
    closure 判断是否是闭包
    闭包的作用

    1. 保证数据的安全性
      2. 装饰器的本质

    img

    ​ 上面被红色方框框起来的区域就是闭包,被蓝色圈起来的那个变量应该是make_averager()函数的局部变量,它应该是随着make_averager()函数的执行结束之后而消失。但是他没有,是因为此区域形成了闭包,series变量就变成了一个叫自由变量的东西,averager函数的作用域会延伸到包含自由变量series的绑定。也就是说,每次我调用avg对应的averager函数 时,都可以引用到这个自用变量series,这个就是闭包。

    闭包的定义:

    ​ \1. 闭包是嵌套在函数中的函数。

    ​ \2. 闭包必须是内层函数对外层函数的变量(非全局变量)的引用。

    如何判断判断闭包?:

    img

    [复制代码](javascript:void(0)😉

    # 例一:
    def wrapper():
        a = 1
        def inner():
            print(a)
        return inner
    ret = wrapper()
    
    # 例二:
    a = 2
    def wrapper():
        def inner():
            print(a)
        return inner
    ret = wrapper()
    
    
    # 例三:
    
    def wrapper(a,b):
        def inner():
            print(a)
            print(b)
        return inner
    a = 2
    b = 3
    ret = wrapper(a,b)
    

    [复制代码](javascript:void(0)😉

    以上三个例子,最难判断的是第三个,其实第三个也是闭包,如果我们每次去研究代码判断其是不是闭包,有一些不科学,或者过于麻烦了,那么有一些函数的属性是可以获取到此函数是否拥有自由变量的,如果此函数拥有自由变量,那么就可以侧面证明其是否是闭包函数了(了解):

    img

    [复制代码](javascript:void(0)😉

    def make_averager():
    
        series = []
        def averager(new_value):
            series.append(new_value)
            total = sum(series)
            return total/len(series)
    
        return averager
    avg = make_averager()
    # 函数名.__code__.co_freevars 查看函数的自由变量
    print(avg.__code__.co_freevars)  # ('series',)
    当然还有一些参数,仅供了解:
    
    # 函数名.__code__.co_freevars 查看函数的自由变量
    print(avg.__code__.co_freevars)  # ('series',)
    # 函数名.__code__.co_varnames 查看函数的局部变量
    print(avg.__code__.co_varnames)  # ('new_value', 'total')
    # 函数名.__closure__ 获取具体的自由变量对象,也就是cell对象。
    # (<cell at 0x0000020070CB7618: int object at 0x000000005CA08090>,)
    # cell_contents 自由变量具体的值
    print(avg.__closure__[0].cell_contents)  # []
    

    [复制代码](javascript:void(0)😉

    闭包的作用:保存局部信息不被销毁,保证数据的安全性。

    闭包的应用

    1. 可以保存一些非全局变量但是不易被销毁、改变的数据。
    2. 装饰器。
    posted @ 2019-10-03 17:44  luckinlee  阅读(197)  评论(0编辑  收藏  举报