装饰器(Decorators)是 Python 的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短,也更Pythonic(Python范儿)。大多数初学者不知道在哪儿使用它们,所以我将要分享下,哪些区域里装饰器可以让你的代码更简洁。
首先,简单举个例子:
函数参数传递:
import time
def square(x):
return x * x
def print_running(f, x):
print(f"{f.__name__} 正在运行")
return f(x)
result = print_running(square, 2)
print(result)
说明了函数也可以作为参数进行传递
再看下一个例子:
无参装饰器
# def decorator(func):
# def wrapper(*args, **kwargs):
# #打印函数正在运行的消息
# print(f"{func.__name__} is running.")
# #记录函数开始执行的时间
# start_time = time.time()
# #调用原始函数,并传递所有接收到的参数
# result = func(*args, **kwargs)
# #记录函数结束执行的时间
# end_time = time.time()
# #打印函数执行所花费的时间
# print(f"{func.__name__} 执行时间:{end_time - start_time}")
# #返回原始函数的执行结果
# return result
# #返回包装函数,它将替代原始函数被调用
# return wrapper
这相当于一个简单的装饰器,对你需要进行修改的函数进行加工
先测试一下不加装饰器的函数情况:
def ceshi():
print("小试身手")
ceshi()
加装饰器的情况:
# @decorator
# def ceshi():
# print("小试身手")
# ceshi()
可以看到,加装饰器的函数,可以在不改动原有函数的基础上增加新的功能,增添新的作用
有参装饰器:
当然装饰器也是可以传参的,我们可以来看一下,先定义一个传参的装饰器:
def timer(threshold):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"{func.__name__} is running.")
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 执行时间:{end_time - start_time}")
if end_time - start_time > threshold:
print(f"{func.__name__} took longer than {threshold} ")
return result
return wrapper
return decorator
不加装饰器的普通函数:
def sleep_o4():
time.sleep(0.4)
print('睡一会')
sleep_o4()
加装饰器的函数:
@timer(0.2)
def sleep_o4():
time.sleep(0.4)
print('睡一会')
sleep_o4()
为什么要使用装饰器:
第一个原因是,使用装饰器可以提升代码复用,避免重复冗余代码。如果我有多个函数需要测量执行时间,我可以直接将装饰器应用在这些函数上,而不是给多个函数加上一样的代码。这样的代码既冗余也不方便后面维护。
第二个原因是,使用装饰器可以保证函数的逻辑清晰。如果一个本身功能就很复杂的函数,我还要通过修改内部代码来测量运行时间,这样会模糊函数自身的主逻辑。同时,软件开发的一个原则就是单一职责,也就是说,一个函数只应该承担一项责任。
第三,通过装饰器,我们可以扩展别人的函数。想象我们正在使用一个第三方库的函数,但我要添加额外的行为,比如测量运行时间,那我就可以用装饰器去包装,而不是跑到库里面去修改。