什么是装饰器

装饰器遵循在不改变装饰对象(函数)原有的“调用方式”和“内部代码”的情况下给被装饰对象添加新的功能。装饰器的原则是对扩展开放,对修改封闭

为什么要用装饰器

在项目完成后,需要在原有的基础上有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况这就用到了装饰器

装饰器的实现

简易版本装饰器

import time


def index():
    time.sleep(3)  # 5.停止3秒
    print("from function index")  # 6.输出


# 要求:给index函数增加了一个统计执行时间的功能
def outer(func):
    def get_time():  # 2.把index函数名绑定给func
        start_time = time.time()  # 3.开始计时
        func()  # 4.调用index函数
        end_time = time.time()  # 计时结束
        print(end_time - start_time)  # index()执行的时间

    return get_time  


index = outer(index)  # 1.通过调用get_time函数把index函数名当做参数传进去
index()  # 可以看做似调用的index其实调用的是get_time
# from function index
# 3.0043959617614746
print(index)  #  全局名称空间中的index指向的是get_time函数体代码
# <function outer.<locals>.get_time at 0x7fcf403edf28>

进阶版本装饰器

# 解决不同函数,需要传的参数个数问题  
def outer(func_name):
    def get_time(*args, **kwargs):
        start_time = time.time()
        func_name(*args, **kwargs)
        end_time = time.time()
        print(end_time - start_time)
    return get_time

完整版本装饰器

# 解决无法返回值问题
def outer(func_name):
    def get_time(*args, **kwargs):
        start_time = time.time()
        res = func_name(*args, **kwargs)
        end_time = time.time()
        print(end_time - start_time)
        return res
    return get_time

装饰器模板(重要)

def outer(func_name):
    def inner(*arg, **wargs):
        print("修改前的操作")
        res = func_name(*arg, **kwargs)
        print("修改后的操作")
        return res
    return inner

装饰器语法糖

# 仅仅是让代码编写的更加好看、简洁!!!
def outer(func_name):
    def inner(*arg, **kwargs):
        print("修改前的操作")
        res = func_name(*arg, **kwargs)
        print("修改后的操作")
        return res

    return inner


@outer  # 等价于 index = outer(index)
def index():
    print("from function index")


index()

装饰器“修复技术”

# 做到比真的还要真  但是本质其实没有变
from functools import wraps


def outer(func_name):
    @wraps(func_name)
    def inner(*arg, **kwargs):
        print("修改前的操作")
        res = func_name(*arg, **kwargs)
        print("修改后的操作")
        return res

    return inner


@outer
def index():
    """这是注释"""
    print('from function index')


help(index)  # help可以查看指定函数的注释信息
index()
# 修改前的操作
# from function index
# 修改后的操作

多层装饰器

"""语法糖会将紧挨着的被装饰对象的名字当做参数自动传入装饰器函数中"""


def outer_1(func_1):
    print('加载了outer_1')

    def inner_1(*args, **kwargs):
        print('执行了inner_1')
        res1 = func_1(*args, **kwargs)
        return res1

    return inner_1


def outer_2(func_2):
    print('加载了outer_2')

    def inner_2(*args, **kwargs):
        print('执行了inner_2')
        res2 = func_2(*args, **kwargs)
        return res2

    return inner_2


def outer_3(func3):
    print('加载了outer_3')

    def inner_3(*args, **kwargs):
        print('执行了inner_3')
        res3 = func3(*args, **kwargs)
        return res3

    return inner_3


@outer_1  # index = outer_1(index)
@outer_2  # index = outer_2(index)
@outer_3  # index = outer_1(outer_2(outer_3(index)))
def index():
    print('from function index')


index()
# 加载了outer_3
# 加载了outer_2
# 加载了outer_1
# 执行了inner_1
# 执行了inner_2
# 执行了inner_3
# from function index

有参装饰器

def outer(source_data):  # 用来给装饰器传递值
    def login_auth(func_name):  # 不能动,只能接收一个被装饰对象名字
        def inner(*args, **kwargs):  # 不能动,是专门用来给被装饰的对象传参的
            if source_data == '1':
                print('操作1')
            elif source_data == '2':
                print('操作2')
            elif source_data == '3':
                print('操作3')
            else:
                print('其他操作')
            res = func_name(*args, **kwargs)
            return res

        return inner

    return login_auth


num = input("输入你要操作的方式:")


@outer(num)
def index():
    print('from function index')


index()
Last modification:March 22, 2022
如果觉得我的文章对你有用,请随意赞赏