一、大前提
闭包函数=名称空间与作用域+函数嵌套+函数对象
核心点:名字的查找关系是以函数定义阶段为准
二、什么是闭包函数
"闭"函数指的该函数是内嵌函数
def f1():
def f2(): #f2函数是闭函数,只能在f1函数内访问
pass
"包"函数指的该函数包含对外层函数作用域名字的引用(不是对全局作用域)
def f1():
x=1
def f2():
x #这种情况f2是包函数,对外层函数f1作用域名字的引用
闭包函数"名称空间与作用域的应用+函数对象"
def f1():
x=1
def f2():
print(x)
f2()
x=333
f1()
#1
def f1():
x=1
def f2():
print(x)
f2() #目前f2函数只能在f1函数内调用
x=333
def foo():
x=222
f1()
foo()
#调用foo函数触发函数体内代码运行
#即产生foo函数内局部名称空间x=222,触发f1函数体内代码运行即产生f1函数内局部名称空间x=1,不会触发该f1函数内的内嵌函数代码体运行,并且f1函数返回内嵌函数函数名。
闭包函数: 函数对象
def f1():
x=1
def f2():
print("函数f2:",x)
return f2 #如果使用了函数对象,可以在全局位置调用局部的f2函数(打破了原先只能在f2函数内调用的限制)
如何在全局调用f2函数
f=f1() #f就是f2函数
print(f)
#<function f1.<locals>.f2 at 0x000000000218B670>
f() #在全局调用f2函数
#函数f2: 1
名字的查找关系是以函数定义阶段为准
x=333
f1()
#调用f1函数触发函数体内代码运行
#即产生f1函数内局部名称空间x=1,不会触发该f1函数内的内嵌函数代码体运行,并且f1函数返回内嵌函数函数名
def bar():
x=444
f1()#调用
bar()
#调用foo函数触发函数体内代码运行
#即产生foo函数内局部名称空间x=444,触发f1函数体内代码运行即产生f1函数内局部名称空间x=1,不会触发该f1函数内的内嵌函数代码体运行,并且f1函数返回内嵌函数函数名。
三、为何要有闭包函数---》闭包函数的应用
两种为函数体传参的方式
方式一:直接把函数体需要的参数定义成形参
def func(x): #或者定义形参为默认值参数x=1
print(x)
func(1)
方式二:
def func():
print(x)
使用函数包起来,缩进代码
def f2():
x=1 #定义一个变量
def func():
print(x) #func函数中就可以用到x
return func #要想func可以在全局位置被调用,就return func(相当于把func内存地址返回到全局)
f=f2()
print(f) #f的内的地址就是func内存地址,相当于在全局拿到了func
#<function f2.<locals>.func at 0x000000000238C940>
f() #加括号就相当于调用func()
使用函数包起来,缩进代码,由于上面传参变量写死了,进行优化
def f2(x):
#x=2 相当于在这儿定义了x=2
def func():
print(x) #func函数中就可以用到x
return func #要想func可以在全局位置被调用,就return func(相当于把func内存地址返回到全局)
f=f2(2)
print(f)#f的内的地址就是func内存地址,相当于在全局拿到了func
f() #加括号就相当于调用func()