• Python闭包Closure 2


      由于Python中,变量作用域为LEGB,所以在函数内部可以读取外部变量,但是在函数外不能读取函数内的变量。但是出于种种原因,我们需要读取函数内的变量时候怎么办?那就是在函数内在加一个函数。

    1 def outer():
    2     x = 5
    3     def inner():
    4         print(x)
    5     return inner
    6 
    7 a = outer()
    8 a()#print 5

    这样,我们就可以看到函数内部的变量了。

    上面的inner就是闭包,闭包就是能够读取其他函数内部变量的函数,也就是定义在函数内部的函数,在本质上来说,闭包就是连接函数内和函数外的桥梁。同时,闭包也可以理解为可以携带状态的函数,可以用这个特性构建类似于类private变量,携带状态的回调函数等。

    闭包有两大作用,一个是像上面的可以读取函数内部的变量,一个是让这些变量的值始终保存在内存中。

     1 def outer():
     2     n = 999
     3     def tr():
     4         nonlocal n
     5         n = n+1
     6     def inner():
     7         print(n)
     8     return tr,inner
     9 
    10 tr,a = outer()
    11 a()#print999
    12 tr()
    13 a()#print1000

    因为outer为inner的父函数,而inner被赋值给了一个全局变量,这导致inner和inner依赖的outer常驻内存

    需要注意的是,返回的函数并没有立马执行,直到调用时候才开始执行。

    def outer():
        acts = []
        for i in range(5):
            acts.append(lambda x:i**x)
        return acts
    
    acts = outer()
    for i in range(5):
        print(acts[i](2))
    #print
    #16
    #16
    #16
    #16
    #16

    输出为五个16而不是我们想要的结果,为什么?

    就是因为act[i]在内存中一直没有执行,一直等到调用才开始执行的,那怎么办?

    方法就是用函数的参数绑定循环变量的值,这样无论循环变量的值怎么改变,已经绑定到函数参数的值不会改变

     1 def outer():
     2     acts = []
     3     for i in range(5):
     4         acts.append(lambda x,i=i:i**x)
     5     return acts
     6 
     7 acts = outer()
     8 for i in range(5):
     9     print(acts[i](2))
    10 #print
    11 #0
    12 #1
    13 #4
    14 #9
    15 #16

    使用闭包时候要注意:

    1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

    2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

    参考资料:学习javascript闭包

          Javascript闭包

         Python学习手册p431

         Python Cookbook

  • 相关阅读:
    LightOJ 1422 Halloween Costumes(区间dp)
    zoj 3537 Cake(区间dp)
    POJ 2955 Brackets(区间dp)
    HDU 1058 Humble Numbers(dp)
    uva 10934 Dropping water balloons(转载)
    树形dp
    Manacher算法求回文半径
    poj-1236.network of schools(强连通分量 + 图的入度出度)
    hdu-2255.奔小康赚大钱(最大权二分匹配)
    poj-2289.jamies contact groups(二分答案 + 二分多重匹配)
  • 原文地址:https://www.cnblogs.com/fcyworld/p/6590834.html
Copyright © 2020-2023  润新知