一文知道什么是python 装饰器

python 装饰器

闭包

1.理解装饰器前先理解什么叫闭包

条件:
1. 外部函数中定义了内部函数
2. 外部函数是有返回值
3. 返回的值是:内部函数名
4. 内部函数引用了外部函数的变量
格式:
def 外部函数():
    ......
    def 内部函数():
        ..........
    return 内部函数

2.来看看闭包的几个例子

例子1
# 闭包
# 在函数中提出的概念,
def func():
    a = 100

    def inner_func():
        b = 99
        print(a, b)
    return inner_func  # 将函数名返回


# print(a)
# inner_func ()
x = func()  # x接收函数 即inner_func()函数
# 那x只要一加括号代表是调用inner_func()
x()

-------------------------------------------------------------
# 输出
100 99
例子2
def func(a, b):
    c = 1

    def inner_func():
        s = a + b + c
        print('相加之后的结果:', s)

    return inner_func


# 调用函数func
ifunc = func(3, 4)  # ifung就是inner_ func  ifunc=inner_ func
# 调用返出来的函数
ifunc()

-------------------------------------------------------------
# 输出
相加之后的结果: 8

3.闭包简单来说函数内嵌套函数,同时使用外部函数的变量,并将内嵌函数名返回

4.闭包有什么缺点和优点

  • 缺点
    • 作用域没有那么直观
    • 因为变量不会被垃圾回收所以有一定的内存 占用问题。
  • 作用
    • 可以使用同级的作用域闭包作用
    • 读取其他元素的内部变量闭包作用:
    • 延长作用域
  • 闭包总结
    • 闭包看似优化了变量,原来需要类对象完成的工作,闭包也可以完成

    • 由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存

    • 闭包的好处,使代码变得简洁,便于阅读代码。

    • 闭包是理解裝饰器的基础

接下来进入正题装饰器

1. 函数A是作为参数出现的(函数B就接收函数A作为参数)
2. 要有闭包的特点

1.举个栗子

例子1
# 定义一个装饰器
def decorate(func):
    a = 100
    print('wrapper打印测试.........')

    # 对函数包装
    def wrapper():
        func()
        print('装饰第一步', a)
        print('装饰第二步')

    print('wrapper加载完成............')

    return wrapper


@decorate
def house():
    print('未装修的房子')

# 调用装饰器
#此时的house并不是原来的函数了而是wrapper()这个函数了
house()

-----------------------------------------------------------
# 输出
wrapper打印测试.........
wrapper加载完成............
未装修的房子
装饰第一步 100
装饰第二步

解释:

1.house被装饰函数,
2.将被装饰函数作为参数传给装饰器decorate
3.执行decorate函数
4.将返回值又赋值给house
例子2
# 定义一个装饰器
def decorate(func):
    def wrapper(*args, **kwargs):
        print('校验中........')
        time.sleep(3)
        print('校验完毕..........')
        # 调用原函数
        func(*args, **kwargs)

    return wrapper


@decorate
# 原函数
def f1(name, age):
    print('他的名字叫{},年龄是{}'.format(name, age))


f1('zs', 21)

-----------------------------------------------------------
校验中........
校验完毕..........
他的名字叫zs,年龄是21

例子3:

多个装饰器一起使用,谁距离函数最近就优先使用哪个装饰器
# 定义装饰器
def decorate1(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        print('装门..........')

    return wrapper


def decorate2(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        print('刷漆..........')

    return wrapper


@decorate2
@decorate1
def house():
    print('我是毛坯房')
house()

----------------------------------------------------------------

# 输出
我是毛坯房
装门..........
刷漆..........

例子4

带参数的装饰器
  1. 带参数的装饰器是三层的
  2. 最外层的函数负责接收装饰器的参数
  3. 里面的内容还是原装饰器的内容饰器
# 装饰器带参数
def outer(a):  # 第一层 负责接收装饰器的参数
    def decorate(func):  # 第二层 负责接收函数的
        def wrapper(*args, **kwargs):  # 第三层 负责接函数的实参
            func(*args, **kwargs)
            print('---->铺地砖{}块'.format(a))#使用装饰器传入的参数

        return wrapper  # 返出来的是:第三层

    return decorate  # 返出来的是:第二层


@outer(10)  # 装饰器带参数表示有三层
def house(time):
    print('我在{}日期拿到房子的钥匙,是毛坯房....'.format(time))


house('2020-05-09')

------------------------------------------------------------
# 输出
我在2022-04-28日期拿到房子的钥匙,是毛坯房....
---->铺地砖10

猜你喜欢

转载自blog.csdn.net/m0_49501453/article/details/124484832