闭包与装饰器,是一个迈入高级阶段比修的内容。首先要熟悉global和nonlocal的用法。
# 没使用全局变量时,函数参数,生命周期是函数内容,印象不了全局变量
n = 0
def f(n):
n = n + 1
return n
f(0)
n # 输入为0
# 但函数内容的变量声明为全局变量时,就可以改变函数外部的变量值。
n = 0
def f():
global n
n = n + 1
return n
f()
n # 输入1
# 外部函数,嵌套了一个内容函数,内部函数定义了global
m = 0
def outer():
m = 2
def inner():
global m
m = m + 1
return m
inner()
return m
print(outer()) # 输入2
m # 输出1
# 可以将inner内层函数中的变量,声明为nolocal,引用外层的变量
m = 0
def outer():
m = 2
def inner():
nonlocal m
m = m + 1
return m
inner()
return m
print(outer()) # 输入3
m # 输出0,outer中并没有引用全局变量
闭包函数, 闭包的三个条件
1. 必须要有嵌套结构,外层\内层
2. 在内层函数要有对外层函数的参数有引用nonlocal
3. 外层的返回值是内层函数
例1:
def outer(n):
def inner(m):
nonlocal n
n = n + m
return n
return inner
x = outer(6)
x(4) # 输出了10
例2: 跳一跳
# 跳一跳
def start(n=0):
def step(m=1):
nonlocal n
n += m
return n
return step
go = start() # 默认从0开始跳
go() # 默认每次跳1步 1
go(4) # 也可以跳4步 5
go100 = start(100) # 可以从100开始跳
go100() # 默认跳一步 101
go100(10) # 也可以跳n步 111
1. 闭包保持了外层函数的生命周期
2. 可以用闭包来写装饰器
例3: 外层函数的参数是一个函数的情况
def wel(fn):
def inner():
return "你好,"+fn()
return inner
def f():
return "这里是北国商城."
a = wel(f)
a() # '你好,这里是北国商城.'
以上代码其实就是装饰器的原理.
装饰器一定一个闭包
区别: 外层函数的参数是一个函数,不用写nonlocal
不改变函数内部代码,却能改变函数输出
def wel(fn):
def inner():
return "你好,"+fn()
return inner
@wel
def f():
return "这里是北国商城."
f() # 内部代码没变,输出为:'你好,这里是北国商城.'
练习1:
def wel(fn):
def inner(n):
return fn(n) + 2
return inner
@wel
def add(n):
return n
add(4) # 输出6
练习2:
def wel(fn):
def inner(n):
return fn(n + 2)
return inner
@wel
def add(n):
return n * 2
add(5) # 14
留言