闭包函数:内部函数包含对外部作用域而非全局作用域名字的引用,并且一般外部函数的返回值为内部函数,这个内部函数叫做闭包函数。
闭:内部函数
包:内部函数引用了外部函数作用域的名称
闭包函数示例:
def outter(): x = 111 def inner(): print(x) return inner res = outter() #res 就是内部函数 inner
下面这个就不是闭包函数:
x = 1 def outter(): def inner(): print(x) return inner 说明:因为x是全局作用域的变量,内部函数inner,包含的是全局作用域x的引用,根据闭包函数的定义,只有包含局部作用域名称的引用才是闭包函数。所以inner不是闭包函数。
函数.__closure__的返回值是一个cell对象组成的元组对象的话,那么这个函数是闭包函数。
如果返回值为None,则不是闭包函数。
def outter(): x = 1 y = 2 def inner(): print(x) print(y) print(‘inner‘, inner.__closure__) return inner res = outter() print(res.__closure__[0].cell_contents) print(res.__closure__[1].cell_contents) >>>inner (<cell at 0x1047f9ac8: int object at 0x1045abc00>, <cell at 0x1047f9af8: int object at 0x1045abc20>) >>>1 (x的值) >>>2 (y的值) 说明:__closure__ 返回的长度等于局部作用域的名称的引用数量。可以看到元组中有两个cell,因为在闭包函数inner中,包含了两个局部作用域名称的引用。
Python循环中不包含域的概念:
func_list = [] for i in range(3): def fun(x): return x*i func_list.append(fun) for func in func_list: print(func(3)) >>>6 >>>6 >>>6
当函数参数传入3时,如果想让结果为 0, 3 ,6 时,这时候就要用到闭包
func_list = [] for i in range(3): def outter(i): def fun(x): return x*i return fun func_list.append(outter(i)) for func in func_list: print(func(3)) >>>0 >>>3 >>>6 说明:局部名称空间中,查找名称的顺序在函数定义时就已经确定。
下面这种闭包会报错:
def outter(): a = 1 def inner(): a = a + 1 return a return inner res = outter() res() >>> a = a + 1 UnboundLocalError: local variable ‘a‘ referenced before assignment 说明:在闭包函数inner中,Python将等于号左边的符号视为一个变量,所以inner函数中等于号左边的a是inner函数的局部名称空间的变量。而在=右边时,却使用了a,左边的a+1会先执行然后赋给a,
但是进行a+1的时候,inner会先从局部名称空间中找a这个名称,找到有a,但是这个a是在a+1的后面。程序就会报以上的错。如果局部名称空间没有a,就会往上面的空间找。
再找不到,就会报 a is not defined错误。
原文:https://www.cnblogs.com/KbMan/p/11173574.html