python-闭包

闭包是由函数及其相关的引用环境组合而成的实体

In [2]: def out_func(n): 
   ...:     sum = n 
   ...:     def in_func(): 
   ...:         return sum + 1 
   ...:     return in_func 
   ...:                                                                         

In [3]: in_func1 = out_func(10)                                                 

In [4]: in_func2 = out_func(20)                                                 

In [5]: in_func1()                                                              
Out[5]: 11

In [6]: in_func2()                                                              
Out[6]: 21

闭包发生于函数嵌套且内部函数引用了外部变量,此时外部函数返回的不仅仅是一个内部函数引用,而是内部函数和外部变量的整体,称作闭包。
所以每次单独调用返回的内部函数都可以使用外部函数定义的sum变量。

内部函数定义的变量只是内部函数的局部变量

In [9]: def out_func(n): 
   ...:     sum = n 
   ...:     def in_func(): 
   ...:         sum = 0 
   ...:         print(sum) 
   ...:     print(sum) 
   ...:     return in_func 
   ...:                                                                         

In [10]: in_func = out_func(10)                                                 
10

In [11]: in_func()                                                              
0

python规则指定所有在赋值语句左面的变量都是局部变量
内部函数不能修改外部变量的值,原因即python认为赋值语句的左边是内部函数的局部变量
所以如下操作会报错:

In [15]: def out_func(n): 
    ...:     sum = n 
    ...:     def in_func(): 
    ...:         sum = sum + 1 
    ...:     return in_func 
    ...:      
    ...:                                                                        

In [16]: in_func = out_func(10)                                                 

In [17]: in_func()                                                              
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-17-02b82eddb720> in <module>
----> 1 in_func()

<ipython-input-15-d472b4544d57> in in_func()
      2     sum = n
      3     def in_func():
----> 4         sum = sum + 1
      5     return in_func
      6 

UnboundLocalError: local variable 'sum' referenced before assignment

显然内部函数中的sum作为内部函数的局部变量还没有定义就被调用了

使用外部引用数据类型进行状态保存

In [22]: def out_func(): 
    ...:     sum = [] 
    ...:     def in_func(n): 
    ...:         sum.append(n) 
    ...:         print(sum) 
    ...:     return in_func 
    ...:                                                                        

In [23]: in_func = out_func()                                                   

In [24]: in_func(10)                                                            
[10]

In [25]: in_func(20)                                                            
[10, 20]

虽然内部函数不能修改外部作用域变量,但是如果存储的外部变量只是一个引用地址,那我们就不必修改它而直接使用引用值
这是闭包的一个典型应用,相当于函数内自带了一个容器并可以一直累计存放

原文地址:https://www.cnblogs.com/Peter2014/p/10928893.html