关于python的装饰器运行逻辑

python的装饰器分为:函数装饰器、类装饰器

首先讲一下函数装饰器; 函数装饰器的运行逻辑是通过闭包函数

def decorator_function(func):
    def wrapper(*args, **kwargs):
        # 此段落为需要进行装饰的代码,例:计算运行时间
        start_time = time.time()

        # 此段落为被装饰的函数
        func(*args, **kwargs)
        
        # 完成计算,此处使用睡眠代替
        time.sleep(1)
        end_time = time.time()
        
        # 打印计算时间
        print(f"{func.__name__}使用了{end_time-start_time}秒")
    
    return wrapper


@decorator_function
def test_function01():
    print("我是1号测试函数")


@decorator_function
def test_function02(a, b):
    print(f"我是2号测试函数:我有两个参数{a},{b}")


def test_function03():
    print("我是3号测试函数,我没有使用装饰器")

 这是一个简单的装饰器,分别调用后的结果是:

 三号函数没有使用装饰器,那么想实现等同于装饰器的效果,可以进行以下操作;等同于装饰器的效果,也就是函数装饰器的运行原理

    test_function03 = decorator_function(test_function03)
    test_function03()

但是我发现,如果在装饰器里面加一段打印,添加后如下:

def decorator_function(func):
    print(f"decorator {func.__name__}")
    
    def wrapper(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        time.sleep(1)
        end_time = time.time()
        print(f"{func.__name__}函数操作用时为:{end_time - start_time}")

    return wrapper

此时,再去进行1,2,3 三个函数的操作,会发现结果不一样

test_function01 / test_function02 的打印时间在最前面,而test_function03的打印则是在test_function02结束后才打印出来,说明装饰器的原理的程序最开始运行的时候,会直接将被装饰的使用 function = decorator(function) 进行装饰;

在后面调用的使用也是使用function() 进行调用

带参数的装饰器同理,附上完整代码:

# -*- coding: utf-8 -*-
# @time    :2022/3/26 20:53
# @author  :陶同学
# @phone   :15355449708
# @file    :python_decorator_function.py
# 需求:计算每个函数的操作用时
import inspect
import time


def decorator_function(func):
    print(f"decorator {func.__name__}")

    def wrapper(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        time.sleep(1)
        end_time = time.time()
        print(f"{func.__name__}函数操作用时为:{end_time - start_time}")

    return wrapper


def decorator_with_parameter(*args, **kwargs):
    print("this is function")

    def outer_wrapper(func):
        print("this is outer_wrapper")
        sig = inspect.signature(func)
        binds = sig.bind_partial(*args, **kwargs).arguments
        for key, value in binds.items():
            print(key, value)

        def wrapper(*args2, **kwargs2):
            print("this is wrapper")
            func(*args2, **kwargs2)
            print("wrapper finished!")

        return wrapper

    return outer_wrapper


@decorator_function
def test_function01():
    print("我是1号测试函数")


@decorator_function
def test_function02(a, b):
    print(f"我是2号测试函数:我有两个参数{a},{b}")


def test_function03():
    print("我是3号测试函数,我没有使用装饰器")


@decorator_with_parameter(int, int, int, int, int)
def test_function04(a, b, c, d, e):
    print(f"我是4号测试函数,我使用了带参数的装饰器:{a} {b} {c} {d} {e}")


def test_function05(a, b, c, d, e):
    print(f"我是5号测试函数 {a} {b} {c} {d} {e}")


if __name__ == '__main__':
    test_function01()
    test_function02(3, "g")
    test_function03 = decorator_function(test_function03)
    test_function03()
    test_function04(1, 2, 3, 4, 5)
    test_function05 = decorator_with_parameter(int, int, int, int, int)(test_function05)
    test_function05(1, 2, 3, 4, 5)

类装饰器也类似,在下次直接附上代码以及运行结果:

# -*- coding: utf-8 -*-
# @time    :2022/3/29 19:13
# @author  :陶同学
# @phone   :15355449708
# @file    :python_decorator_class.py
import time


class class_decorator:

    def __init__(self, func):
        self.func = func
        print("this is class")

    def __call__(self, *args, **kwargs):
        print("this is class decorator")
        start_time = time.time()
        self.func(*args, **kwargs)
        time.sleep(1)
        end_time = time.time()
        print(f"{self.func.__name__}用时{end_time - start_time}秒")


@class_decorator
def test_function():
    print("this is a function decorated by class decorator")


def test_function_way():
    print("this function is used to find how to use class function")


if __name__ == '__main__':
    # 使用装饰器运行
    test_function()
    # 不使用装饰器,装饰器的内部运行逻辑
    test_function_way = class_decorator(test_function_way)
    test_function_way()

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值