Python闭包Closure 2

  因为Python中,变量做用域为LEGB,因此在函数内部能够读取外部变量,可是在函数外不能读取函数内的变量。可是出于种种缘由,咱们须要读取函数内的变量时候怎么办?那就是在函数内在加一个函数。javascript

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

这样,咱们就能够看到函数内部的变量了。html

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

 

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

 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常驻内存app

 

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

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]在内存中一直没有执行,一直等到调用才开始执行的,那怎么办?学习

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

 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

 

 

使用闭包时候要注意:3d

1)因为闭包会使得函数中的变量都被保存在内存中,内存消耗很大,因此不能滥用闭包,不然会形成网页的性能问题,在IE中可能致使内存泄露。解决方法是,在退出函数以前,将不使用的局部变量所有删除。

2)闭包会在父函数外部,改变父函数内部变量的值。因此,若是你把父函数看成对象(object)使用,把闭包看成它的公用方法(Public Method),把内部变量看成它的私有属性(private value),这时必定要当心,不要随便改变父函数内部变量的值。

 

参考资料:学习javascript闭包

      Javascript闭包

     Python学习手册p431

     Python Cookbook

相关文章
相关标签/搜索