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()