很多语言都有闭包,那么闭包究竟是什么呢?来看一个简单的例子。
def outer(x):
x+=1
def inner():
print(x)
return x*5
return inner()
a = outer(1)
print(a)
a= outer(2)
print(a)
a=outer(3)
print(a)
首先看上述代码,上述代码就体现了如何产生一个闭包,Outer是我定义的一个外函数,当x变量加完1的时候,注意,此时并不执行inner函数,而是返回了内部函数inner,这里注意一点,如果return后面的inner不带括号,那么outer外部函数最后返回的便是内部函数inner的引用,但是加了括号之后,就表示要执行inner()函数。把inner函数的结果返回给了最后接收的a变量里了。下面看执行结果。
看到这大家会奇怪一个问题,按照正常的内存释放顺序来看,x变量是不存在的了,因为在outer函数返回之前,这段内存就该被释放,那么这就是闭包的优势的体现了,那么总结一下,闭包=函数块+定义函数时的环境,outer就是函数块,x就是环境,当然这个环境可以有很多,不止一个简单的x。所以闭包的本质是什么?当外部函数执行return 时,发现内部函数要用到我的局部变量,那么我就把局部变量临时绑定到内部函数里以供使用。这里其实说的不全对?为什么呢?下面看一个上一个例子的变形。
代码如下:
def outer(x):
def inner():
x=x+1
return x*5
return inner()
a = outer(1)
print(a)
a= outer(2)
print(a)
a=outer(3)
print(a)
结果如下:
为什么呢?这里涉及到一个新知识点,就是python中的变量访问LEGB顺序,就是local-Enclosing-Global-Builtin。什么意思呢?就是如果python查找变量先从本地作用域找,如果没找到就到外层作用域找,还没找到就去全局作用域找,如果还没找到,就去python内置的变量里去找,如果还没找到就抛出异常。那么分析一下上面的例子,首先,这是一个典型错误,是什么呢?就是python闭包的内部函数不允许修改外部作用域的变量。为什么呢?分析如下,当在内部执行x=x+1的时候,当x变量做左值的时候,就相当于修改了原来x变量的引用,相当于在本地作用域又有了一个新的x变量,可是我们知道,本地作用域并没有x,所以当然会抛出异常,所以只要不修改外部作用域与全局作用域的变量,那么在闭包里的内函数可以随意操作这些变量。
那么说了这么多,闭包究竟有什么用呢?
第一 装饰器的实现依赖闭包
第二 函数式编程经常用到闭包,闭包对数据的持久化以及按配置产生不同的功能,是很有帮助的
第三 面向对象编程也经常用到闭包。