一、前置知识
1.在Python中一切皆对象,一个普通变量、一个函数等,都是对象;而这点与很多语言其实是不一样的,在C、C++、C#、Java中函数只是一段可执行的代码,并不是对象。
2.闭包 = 函数 + 环境变量,闭包把上下文环境给保存起来,这样就不会受到外界环境干扰。
3.可以通过 __closure__ 方法来查看闭包的类型。
demo1:
def curve_pre():
a = 25
def curve(x):
return a*x*x
return curve
f = curve_pre()
#print(type(f))
#print(f.__closure__)
print(f.__closure__[0].cell_contents) # 输出a的值为,25
#print(f(2))
demo2:不是闭包,经典问题。
def f1():
a = 10
def f2():
a = 20
return a
return f2
f = f1()
print(f)
print(f.__closure__) # None,f 不是闭包类型
闭包和非闭包 demo对比:
orign = 0
def go(step):
#global orign 加上这行代码就不会报错了
new_pos = orign + step
orign = new_pos
return orign
'''
为什么会报,UnboundLocalError: local variable 'orign' referenced before assignment,这个错误呢?
因为orign在赋值的左边,python解析器会认为 orign = new_pos,orign 是在这一行进行定义的一个局部变量。
而代码上一行 new_pos = orign + step,orign 都没有被定义,怎么能够用orign呢?所以会报错!!!
怎么样修改呢?在go函数里面加上 global orign
'''
print(go(2))
print(go(3))
print(go(6))
##########################################################################
#闭包写法
orign = 0
def factory(pos):
def go(step):
nonlocal pos
new_pos = pos + step
pos = new_pos
return new_pos
return go
tourist = factory(orign)
print(tourist(2))
print(tourist.__closure__[0].cell_contents) # 会保存中间的信息
print(tourist(3))
print(tourist.__closure__[0].cell_contents) # 会保存中间的信息
print(tourist(5))
print(tourist.__closure__[0].cell_contents) # 会保存中间的信息
demo3:
def func(): a = 1 b = 2 return a+b def sum(a): def add(b): return a+b return add num1 = func() num2 = sum(2) print(type(num1)) print(type(num2)) print(num2(8))
demo2:
def counter():
cnt = [0]
def add_one():
cnt[0] += 1
return cnt[0]
return add_one
num1 = counter()
print(num1())
print(num1())
print(num1())
print("\n")
def counter(FIRST=5):
cnt = [FIRST]
def add_one():
cnt[0] += 1
return cnt[0]
return add_one
num5 = counter(5)
print(num5())
print(num5())
闭包的使用
#计算一次函数 y = a*x + b
#不用闭包的写法
def a_line(a,b,x):
return a*x + b
#采用 lambda 的写法
def a_line(a,b):
return lambda x: a*x + b
line1=a_line(3,5)
print(line1(10))
#用闭包的写法
def a_line(a,b):
def arg_y(x):
return a*x + b
return arg_y
line1 = a_line(3,5)
print(line1(10))