【python基础】五、python之装饰器 (划重点)

内部函数

  • 函数里面 定义的 函数 --> 内部函数
    • 内部函数 修改 外部的变量 nonlocal
    • 内部函数 修改 全局的变量 global
a = 100


def func():
    b = 99
    def func_son():
        global a
        nonlocal b
        c = 88
        b += 1
        a += 1
        print(a, b, c)
  • globals() # 查看全局变量、函数
  • locals() # 查看内部变量、函数

闭包

  • 是什么?
    • 函数中 的概念
    • 调用 函数的内部函数、内部变量
    • 函数返回自己的内部函数名,这就是闭包

    return 内部函数名

def func():
    def func_son():
        a = 10
        print(a)
    return func_son     # 不加(), 返回的是函数,不是调用函数
    
x = func()      # x 即为 func_son
x()             # 给x加() 即 调用 func_son()

闭包的参数、变量

  • 闭包的作用域
    • 内部函数每次重新加载,但是 内部函数 访问的仍是同一个外部函数

装饰器

  • 应用广泛,依赖闭包,是在闭包的基础上的升级

条件一 函数作为参数
条件二 闭包的特点

def decrator(func):  # 定义一个装饰器
    a = 100
    def wrapper():  # 包装 装饰
        func()          # 调用被装饰函数,保持其原功能
        print(' wrapper print a :', a)
    return wrapper
    
decrator(xxx)       # 传入函数名 作为参数

如何使用装饰器 @

  • 在简单函数上面 @装饰器名字
# 使用装饰器
@decrator
def house():
    print('i am 毛坯房')

house()

假如在开发完成后,发现house()函数还有不足,需要丰富一下。

  • 更改原函数 – 不可取

    • 不一定所有调用原函数都需要更改
  • 新增一个函数 – 不可取

    • 需要改 原来调用 house()的代码

装饰器 在不改变原函数名、原函数体 的情况下,对函数功能进行修改

# 完整
def decrator(func):  # 定义一个装饰器
    a = 100
    print('wrapper 外层打印 仍然 执行 ')
    def wrapper():  # 包装 装饰
        print(' wrapper print a :', a)
        func()
        print(' 装饰器在原函数的基础上,增加了一个 a:{} 的输出 '.format(a))

    print('即使不调用,由于@decrator,wrapper 外层打印 仍然执行 ')
    return wrapper


# 使用装饰器
@decrator
def house():
    print(' house() :i am 毛坯房, 原函数,保持原功能')


# house()
  • @decrator 步骤分析
  1. 将其下方函数,作为参数 传给decrator()
  2. 底层 默执行decrator()函数,里面的代码
  3. 执行到 wrapper(), 加载wrapper内容(未执行)
  4. 最后 return wrapper
  5. 默认 同名的house 接收 返回的wrapper
    • 打印 wrapper 地址id
    • 打印 此时的 新house 地址id
  6. 下面的新house 即为 wrapper, 其中调用了原house

带有参数的 原函数

  • wrapper 也传入同样参数即可:
def decrator(func):  # 定义一个装饰器
    def wrapper(x):  # 包装 装饰
        func(x)          # 调用被装饰函数,保持其原功能
        print(' wrapper print a :', a)
    return wrapper

万能 传入参数

  • 可变参数
def decrator(func):  # 定义一个装饰器
    def wrapper(*args, **kwargs):  # 包装 装饰
        func(*args, **kwargs)          # 调用被装饰函数,保持其原功能
        print(' wrapper print a :', a)
    return wrapper

两层装饰器

@decrator2
@decrator1
house()

首先 近的decrator1 生效,
然后 decrator2 生效

  • 可以分析:
  1. decrator2 先装饰完
  2. decrator1 装饰 被 decrator2 装饰过的house
  3. 调用的是 被 decrator1 装饰过的 house
  4. 相当于 func(func1(func2()))

装饰器 自带 参数

  • 只要装饰器自带参数
  • 两层装饰器!
def decrator_outer(a):  # 接收 装饰器 参数
    # 原 装饰器
    def decrator(func):  # 接收 函数
        def wrapper(*args, **kwargs):  # 接收 函数参数
            func(*args, **kwargs)  
            print(a)# 调用被装饰函数,保持其原功能
        return wrapper
    # 返回原 装饰器
    return decrator
    
@decrator_outer(3)


在b站学习中,学习链接

个人主页

欢迎 批评 指正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章