1.一切皆对象
python支持函数式编程,但不一定非要用函数式编程
其他语言里,函数只是一段可执行的代码,并不是对象
python里,一切皆对象,简化了学习难度
例如:
def f1():
pass
a = f1()
print(type(f1))
==>
<class 'function'>
在其他语言中把一个函数赋值给一个变量是做不到的;
python可以将一个函数作为另一个函数的参数,传递到另外的函数里,也可以把一个函数当做另外一个函数的返回结果
2.闭包是什么
(1)
def curve_pre():
def curve():
pass
curve()
==>
Traceback (most recent call last):
File ".\c14.py", line 5, in <module>
curve()
NameError: name 'curve' is not defined
#直接调用会报错函数未定义
(2)
def curve_pre():
def curve():
print('This is a funciton')
return curve
curve_pre()
print(type(curve_pre()))
==>
<class 'function'>
#直接调用curve_pre,看不到返回值,其实curve_pre返回了一个函数即curve,
#因此想要看到This is a funciton,需要先把curve赋值给一个变量,再通过这个变量,对curve进行调用,如下:
def curve_pre():
def curve():
print('This is a funciton')
return curve
f = curve_pre()
f()
==>
This is a funciton
(3)
def curve_pre():
a = 25
def curve(x):
return a*x*x
return curve
f = curve_pre()
print(f(2))
==>
100
上面的例子很容易理解,但如果,在调用curve前,再给a重新赋值,a=10,最终结果会等于100还是40?
def curve_pre():
a = 25
def curve(x):
return a*x*x
return curve
a = 10
f = curve_pre()
print(f(2))
==>
100
最终结果等于100,而不是40
这就体现了闭包的作用,不会被外部变量赋值影响;闭包=函数+环境变量
环境变量一定要在函数的外部,但是还不能是全局变量(这是一个很重要的特点)
print(f.__closure__)
print(f.__closure__[0].cell_contents)
==>
#上方的return curve语句,返回的不仅仅是def curve,同时把环境变量a=25也返回了
(<cell at 0x00000273ED0A6D68: int object at 0x00007FFF1BAC9640>,)
25
(4)看看下边这个例子能不能理解
def f1():
a = 10
def f2():
a = 20
print(a) #a此时被python认为是一个局部变量,不会影响到外部的变量
print(a)
f2()
print(a)
f1()
==>
10
20
10
3.闭包怎么用
假设一个人在x轴上行走,初始位置x=0,第一次走了2步,result=2;第二次走了3步,result=5;第三次走了6步,result=11,这个需求怎么实现?
(1)非闭包方式1
origin = 0
def go(step):
new_pos = origin + step
origin = new_pos
return origin
print(go(2))
print(go(3))
print(go(6))
==>
Traceback (most recent call last):
File ".\c14.py", line 37, in <module>
print(go(2))
File ".\c14.py", line 34, in go
new_pos = origin + step
UnboundLocalError: local variable 'origin' referenced before assignment
#因为origin在=前出现了,python就认为origin是一个局部变量,而执行到第4行的时候,origin并没有被定义,因此报错
(2)
origin = 0
def go(step):
new_pos = origin + step
return new_pos
print(go(2))
print(go(3))
print(go(6))
==>
2
3
6
# 并没有输出想要的结果,每次调用origin都为0
(3)
origin = 0
def go(step):
global origin
new_pos = origin + step
origin = new_pos
return new_pos
print(go(2))
print(go(3))
print(go(6))
==>
2
5
11
# 实现了功能,但是有一个弊端,全局变量origin,很容易在另一个函数或者过程中被赋上新值,这样go的返回值就可能发生改变,下面来看用闭包如何实现
(4)
origin = 0
def factory(pos):
def go(step):
new_pos = pos + step
pos = new_pos
return new_pos
return go
tourist = factory(origin)
print(tourist(2))
print(tourist(3))
print(tourist(5))
==>
Traceback (most recent call last):
File ".\c14.py", line 41, in <module>
print(tourist(2))
File ".\c14.py", line 35, in go
new_pos = pos + step
UnboundLocalError: local variable 'pos' referenced before assignment
# 报错:局部变量没有被定义
(5)
origin = 0
def factory(pos):
def go(step):
nonlocal pos
new_pos = pos + step
pos = new_pos
return new_pos
return go
tourist = factory(origin)
print(tourist(2))
print(tourist(3))
print(tourist(6))
==>
2
5
11
得到了想要的结果,验证一下每一步全局变量origin有没有被改变
origin = 0
def factory(pos):
def go(step):
nonlocal pos
new_pos = pos + step
pos = new_pos
return new_pos
return go
tourist = factory(origin)
print(tourist(2))
print(origin)
print(tourist(3))
print(origin)
print(tourist(6))
print(origin)
==>
2
0
5
0
11
0 #全局变量origin一直没有被改变
再来看看函数tourist的环境变量是不是一直在变化
origin = 0
def factory(pos):
def go(step):
nonlocal pos
new_pos = pos + step
pos = new_pos
return new_pos
return go
tourist = factory(origin)
print(tourist(2))
print(tourist.__closure__[0].cell_contents)
print(tourist(3))
print(tourist.__closure__[0].cell_contents)
print(tourist(6))
print(tourist.__closure__[0].cell_contents)
==>
2
2
5
5
11
11
环境变量的状态得到了保存,因此能得到想要的结果
这个环境变量是要常驻内存的,使用时要注意;
除了使用闭包,也可以用面向对象的办法,用类变量来保存环境变量的中间状态
网友评论