闭包是由函数及其相关的引用环境组合而成的实体
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]
虽然内部函数不能修改外部作用域变量,但是如果存储的外部变量只是一个引用地址,那我们就不必修改它而直接使用引用值
这是闭包的一个典型应用,相当于函数内自带了一个容器并可以一直累计存放