首先要知道函数的作用域法则LEGB,可以看下面的链接。一个函数定义后就产生了一个本地域,如果在它内部再定义一个函数,叫嵌套,内部函数也产生了本地域Local。这时相对于内部函数,外部函数的作用域叫嵌套域Enclosed。根据python的LEGB规则,程序运行找名是由内向外找,所以一个嵌套的函数,就封闭了它内部的函数。在它的作用域外是无法直接调用它内部的函数的。例如:def out_1(): a=2 def inner_1(): b=5 return a*b print(inner_1()) inner_1()在out_1函数的作用域外是无法调用inner
嵌套域内可以自由调用内部函数:def out_2(): a=2 def inner_2(): b = 5 return a*b s=inner_2() return s print(out_2())---10
外部函数返回内部函数的函数名:def out_2(): a=2 def inner_2(): b = 5 return a*b return inner_ inner=out_2() print(inner)---
一个函数名加上圆括号就是才能在调用时被执行。所以如果先得到返回结果(函数名),再加括号,就等于间接的在外部调用了内部函数。入上例,在变量inner后加上圆括号def out_2(): a=2 def inner_2(): b = 5 return a*b return inner_ inner=out_2() print(inner())---10将内部函数名的变量inner加上圆括号就实现了一个函数。
为了更逼真,可以将变量名写成与内部函数名相同,就会变成和内部函数一样的效果,inner_2()def out_2(): a=2 def inner_2(): b = 5 return a*b return inner_2 inner_2=out_2() print(inner_2())此时的inner_2()和out_2()同处在全局域Global内。这个inner_2就是个闭包函数。
在其他函数调引用闭包的情况。def out_2(): a=2 def inner_2(): b = 5 return a*b return inner_2 inner_2=out_2() print(inner_2()) def fun(): a=100 print(inner_2()) fun()可以看到,函数fun中的变量a=100并没有影响到inner_2()的值。同样是遵守了LEGB的规则,inner_2引用a首先找到的是它上层的a=2。
可以通过一个函数的特殊属性 __closure__来验证。__closure__是一个内存地址的特殊属性,返回的是个元组,包含内部函数调用的嵌套域的变量地址。可以用cell_contents来查看这些变量值。例如:def myOut(): a=20 b=50 e=60 def myInner(): c = 30 return a+b+c return myInner myInner=myOut() a=myInner() print(myInner.__closure__)(
总结实现一个闭包函数:1)函数有嵌套。2)内部函数引用了嵌套域内的变量,并有返回结果。3)外部函数返回内部函数的函数名。4)外部函数被调用时加圆括号,就实现了闭包函数。