之所以出现闭包就是因为在不同的作用域下出现了同名的变量
(找变量要是没找到就会向它上级去找)
# 闭包
# 函数式编程 javascript python
# 函数任意位置的定义
# 函数可以作为另外一个函数的返回值,或者参数来使用
# python 一切皆对象 函数也是对象
def a():
def b(): # b是函数名字
pass
def c(b): # b是形参
pass
c(b) # b是实参
return b
print(type(a))
# 内部函数定义在外部函数内部
def func_out():
def func_in():
print('i am in func_in')
return func_in
f = func_out()
print(type(f))
f() # 调用内部函数
# 美元转换人名币 汇率 6
# 闭包 函数+环境变量 环境参数 才可以产生闭包
def func_out():
rate = 6
def transfer(doller):
return doller * rate
return transfer
# rate = 7 # 7并没有改变局部变量的6,闭包现象
f = func_out()
print(f(10))
rate在局部作用域找不到会向上一层去找,要是找不到会再往外层去找,最后找到全局变量6
rate = 6 # 全局变量定义6
def func_out():
def transfer(doller):
return doller * rate
return transfer
rate = 7 # 全局变量改变
f = func_out()
print(f(10))
实际应用中,为了防止混淆,作用域不同,变量名也应不同
def func1():
x = 1
def func2():
x = 2
print(x) # 第二个打印的,为2
print(x) # 第一个打印的,为1
func2() # 调用func2()
print(x) # 第三个打印的,为1;出了func2()的,变量都为func1()的
func1()
def func1():
x = 1
def func2():
y = 2
print(y) # 第二个打印的,为2
print(x) # 第一个打印的,为1
func2() # 调用func2()
print(x) # 第三个打印的,为1;出了func2()的,变量都为func1()的
func1()
作用域的知识点:在定义函数里,只要变量出现在左边并且进行赋值操作,都会被认为是局部变量
# 解释作用域的知识点
# 在定义函数里,只要变量出现在左边并且进行赋值操作,都会被认为是局部变量
x = 1
def a():
y = 2 * x
print(y)
print(x)
a()
闭包有什么用
下一次结果比较依赖上一次执行结果时,比较适合闭包理论(环境参数,保存现场)
旅行者一维变量举例:
错误代码
(注释掉错误那一行也不能实现我们预期目标)
# 一维坐标 x从 0到 2 到 4
origin = 0
def gogo(step):
target = origin + step
origin = target # 因为origin出现在了左边,被认为是局部变量,必须先赋值再使用
return target
print(gogo(2))
print(gogo(3))
print(gogo(6))
不使用闭包的情况,用一个全局变量来记录每一次调用完的结果
正确代码
# 一维坐标 x从 0到 2 到 4
origin = 0
def gogo(step):
global origin # 用global关键字定义为全局变量
target = origin + step
origin = target
return target
print(gogo(2))
print(gogo(3))
print(gogo(6))
使用闭包
用关键词nolocal
origin = 0
def creater(start):
def gogo(step):
nonlocal start # 扩大作用域,但不是全局变量
target = start + step
start = target
return target
return gogo
f = creater(origin)
print(f(2))
print(f(3))
print(f(6))
使用闭包比较安全,第一种全局变量方法容易被修改,比如:
修改起始为100,后面也会随之变化
origin = 0
def gogo(step):
global origin # 用global关键字定义为全局变量
target = origin + step
origin = target
return target
print("or", origin)
print(gogo(2))
print("or", origin)
print(gogo(3))
origin = 100
print("or", origin)
print(gogo(6))
print("or", origin)
而闭包不会
封闭包裹,将环境变量和函数的执行过程封闭在了一个私有的包里面