前导
- 在学习了闭包后,我们知道在函数里面嵌套一个子函数,子函数可以调用父函数的变量
- 在学习了回调函数后,我们知道函数名可以作为参数传递
还不了解的可以翻一下前面的篇章【Python】函数「二」——闭包和回调函数学习一下,在了解闭包和回调函数后,装饰器就很好理解了
什么是装饰器
简单来说,装饰器就是在不改变原函数定义代码的情况下,根据需求对函数进行修改(或者说装饰)。这里我们先看一个简单的例子
import time
# sleep 0.5秒,然后输出hello world
def hello():
time.sleep(0.5)
print("hello world")
# 定义一个装饰器,接收函数func为参数
# 在函数开始前记录下当前时间,在函数结束后输出函数总用时
def print_time(func):
def wrapper():
start = time.time()
func()
print("total time:", time.time()-start)
return wrapper
# 为hello函数装饰
hello_ = print_time(hello)
hello_()
装饰带参数的函数
import time
# sleep s秒,然后输出hello world
def hello(s):
time.sleep(s)
print("hello world")
def print_time(func):
# print_time(func)返回函数对象
def wrapper(*args, **kwargs):
start = time.time()
# 参数的嵌套传递,print_time(func)(*args, **kwargs)返回值
func(*args, **kwargs) # 这里如果看不懂,可以参考我之前的博客——函数的参数传递
print("total time:", time.time()-start)
return wrapper
# 为hello函数装饰
hello_ = print_time(hello)
hello_(1) # 相当于print_time(hello)(1)
使用语法糖,更便捷地装饰函数
这是一开始的例子,咱们利用语法糖”@+装饰器函数名“可以直接对原函数进行装饰
import time
# 定义一个装饰器,接收函数func为参数
def print_time(func):
def wrapper():
start = time.time()
func()
print("total time:", time.time()-start)
return wrapper
@print_time # 为hello函数装饰
def hello():
time.sleep(0.5)
print("hello world")
hello()
带参数的装饰器
有时候我们需要为某几类函数写装饰器,除了一小部分配置值外其余完全一致,那么我们就可以把配置信息独立为参数,在普通装饰器外面再嵌套一层即可。下面这个例子还是一开始的例子,这次我们希望能够在装饰器上指定函数func的运行次数:
import time
# 运行func函数num次
def run_again(num):
def print_time(func):
def wrapper():
start = time.time()
for _ in range(num):
func()
print("total time:", time.time()-start)
return wrapper
return print_time
@run_again(3)
def hello():
time.sleep(0.5)
print("hello world")
hello() # 相当于run_again(3)(hello)()
保留被装饰函数的注释
在装饰函数后,我们会发现原函数的注释被替换掉了
那么,如何保留注释呢?也很简单,请看代码:
import time
from functools import wraps # 引入functools中的wraps
def print_time(func):
@wraps(func) # 使用wraps装饰器保留注释
def wrapper():
"""
这里是wrapper
"""
start = time.time()
func()
print("total time:", time.time()-start)
return wrapper
@print_time
def hello():
"""
hello world
"""
time.sleep(0.5)
print("hello world")
print(hello.__doc__)
如果我的分享能帮助到你,那我的分享就多了一份意义;如果有错误的地方劳烦指出,期待共同进步!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/97103.html