立即登录

注册账号

联系我们

2021年12月22日 19:08

9. 闭包与装饰器

闭包与装饰器,是一个迈入高级阶段比修的内容。首先要熟悉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

留言

给我留言