扩充:
- 函数式编程(淡化)
- 函数只是一段可执行的代码,不可以实例化,并不是对象
- 一切皆对象、python 另外一个函数的参数,传递到另外的函数里;把一个函数当做是另一个函数的返回结果:
def a():
pass
print(type(a))
#>>><class 'function'>
步入正题:闭包=函数+环境变量(函数定义时候的环境变量,不能是全局变量)
闭包是函数式编程的一种
1、闭包的形式及使用
#闭包
def curve_pre():
b=25
def curve(x):#曲线
return b*x*x
return curve
#curve()在外部不可以直接调用
b=10
f=curve_pre()
print(f.__closure__)#__closure__内置函数存放闭包的环境变量信息,返回的是闭包
#>>>(<cell at 0x0261B750: int object at 0x6DF7BFC8>,)
print(f.__closure__[0].cell_contents)
#>>>25 输出环境变量的值
f(2)#执行函数==>curve(2)
print(f(2))
#>>>100
#不会因为全局变量而输出40,而是使用环境变量a=25
__closure__内置函数存放闭包的环境变量信息,返回的是闭包
__closure__[0].cell_contents
#>>>25 输出环境变量的值
输出结果:
>>>
<class 'function'>
(<cell at 0x0261B750: int object at 0x6DF7BFC8>,)
25
100
延伸:单个函数f1(),a是全局变量,f1()函数在找不到a的值的情况下会调用全局变量a=10
a=10
def f1(x):
return a*x*x
f1(2)
print(f1(2))
#>>>40
闭包的经典误区:
例子:
def f2():
c=10
def f3():
c=20
print(c)#②2>>>20
print(c)#①1>>>10
f3()
print(c)#③3>>>10
f2()
输出结果:
>>>10
20
10
改动判断是不是闭包:
#改动判断是不是闭包
def f2():
c=10
def f3():
#此时将被python认为是一个局部变量
c=20
return c
return f3
w=f2()
print(w)
print(w.__closure__) #在这里这个属性__closure__是没有的
输出:
>>><function f2.<locals>.f3 at 0x008AE030>
None
重点!!!:在这里这个属性__closure__是没有的,其实因为c=20存在,它此时将被python认为是一个局部变量,内部函数输出的是局部变量而不是环境变量,不满足闭包的要求,所以实质上此时还不是一个闭包
再改进:
def f2():
c=10
def f3():
#此时内部函数中只是引用了c
d=20*c
return c
return f3
w=f2()
print(w)
print(w.__closure__)
输出:
<function f4.<locals>.f5 at 0x08896E88>
(<cell at 0x0371FB10: int object at 0x6DF7BED8>,)
此时根据print(w.__closure__)返回的信息(<cell at 0x0371FB10: int object at 0x6DF7BED8>,)得知是一个闭包
用闭包来解决一个问题:旅行者,每走一步加一,编写函数得到当前的位置
1、非闭包形式解决:
origin=0
def go(stpe):
global origin
new_pos=origin+stpe
origin=new_pos
return new_pos
print(go(2))#>>>2
print(go(3))#>>>5
print(go(6))#>>>11
2、闭包形式解决:
origin1=0
def factory(pos):
def go1(stpe):
#强制声明pos不是局部变量
nonlocal pos
new_pos=pos+stpe
pos=new_pos
return new_pos
return go1
tourist=factory(origin1)
print(tourist(2))#>>>2
print(origin1)#>>>0
print(tourist.__closure__[0].cell_contents)#>>>2
print(tourist(3))#>>>5
print(origin1)#>>>0
print(tourist.__closure__[0].cell_contents)#>>>5
print(tourist(6))#>>>11
print(origin1)#>>>0
print(tourist.__closure__[0].cell_contents)#>>>11
输出:
2
0
2
5
0
5
11
0
11