python中的闭包

一 .定义
  如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).这个定义是相对直白的,

闭包有三个条件:

  1.函数嵌套 

  2,内部函数调用外部函数的变量 

  3.返回内部函数

def a(a):
    def B(b):
        s = a + b
        return s
    return B
cd =a(6)
ss = cd(4)
print(ss)#结果为10

 二 闭包中注意的事项

  闭包中是不能修改外部作用域的局部变量的值

1 def foo():  
2     m = 0  
3     def foo1():  
4         m = 1  
5         print(m)  
6     print(m)  
7     foo1()  
8     print(m)
9 foo()  

###########################
0
1
0

以下这段代码是在python中使用闭包时一段经典的错误代码

这段程序的本意是要通过在每次调用闭包函数时都对变量a进行递增的操作。但在实际使用时

def foo():  
    a = 1  
    def bar():  
        a = a + 1  
        return a  
    return bar 

  这是因为在执行代码 c = foo()时,python会导入全部的闭包函数体bar()来分析其的局部变量,python规则指定所有在赋值语句左面的变量都是局部变量,则在闭包bar()中,变量a在赋值符号"="的左面,被python认为是bar()中的局部变量。再接下来执行print c()时,程序运行至a = a + 1时,因为先前已经把a归为bar()中的局部变量,所以python会在bar()中去找在赋值语句右面的a的值,结果找不到,就会报错。解决的方法很简单,使用语句nonloacal a就可以了,该语句显式的指定a不是闭包的局部变量。

方法一

def foo():  
    a = [1]  
    def bar():  
        a[0] = a[0] + 1  
        return a[0]  
    return bar 

方法二

def foo():  
    a = 1  
    def bar():
        nonlocal a  
        a = a + 1  
        return a  
    return bar  
c = foo()
print(c())

经典错误问题:

flist = []  
for i in range(3):  
    def foo(x): 
print x + i flist.append(foo) for f in flist: f(2)

  可能有些人认为这段代码的执行结果应该是2,3,4.但是实际的结果是4,4,4。这是因为当把函数加入flist列表里时,python还没有给i赋值,只有当执行时,再去找i的值是什么,这时在第一个for循环结束以后,i的值是2,所以以上代码的执行结果是4,4,4.解决方法也很简单,改写一下函数的定义就可以了。

for i in range(3):  
    def foo(x,y=i): 
        print x + y  
    flist.append(foo)        

 

 

 

三 闭包的用途

  1 .当闭包执行完后,仍然能够保持住当前的运行环境。

  2.闭包可以根据外部作用域的局部变量来得到不同的结果,这有点像一种类似配置功能的作用,我们可以修改外部的变量,闭包根据这个变量展现出不同的功能。

1 def make_filter(keep):  
2     def the_filter(file_name):  
3         file = open(file_name)  
4         lines = file.readlines()  
5         file.close()  
6         filter_doc = [i for i in lines if keep in i]  
7         return filter_doc  
8     return the_filter

如果我们需要取得文件"result.txt"中含有"pass"关键字的行,则可以这样使用例子程序
filter = make_filter("pass")  
filter_result = filter("result.txt") 

 

posted @ 2019-05-06 20:35  taysem  阅读(235)  评论(0编辑  收藏  举报