说装饰器之前,先举一个生活的例子,比如秋天的时候,我们只穿一件夹克就可以保暖,但是到了冬天的时候,我想让这件夹克更加保暖一点,给夹克加点棉,到春天的时候,天气那么冷了,还想穿这件夹克,但是因为加了棉,会比较热,需要把棉去掉。但是这样显得比较麻烦,假如我们在不改变夹克的基础上,我们穿一件保暖衣服,天气热的时候就脱掉,让我们随时能够保暖也不至于太热,这个保暖衣服就有点相当于python的装饰器,python装饰器可以扩展原来函数的功能,并且不改变原来函数,用好装饰器,有时候能让我写代码事半功倍。
一、体验装饰器
请看以下函数,现在有一个需求是统计sleep_time函数的运行时间,这时候我可能第一时间,应该会增加一个函数用来统计sleep_time的运行,原谅我这么笨。但是如果我们需要统计其他函数呢?又编写其他函数来统计吗?那岂不是要命?装饰器很好解决了这个问题,让函数自己增加统计自己运行的时间。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
def sleep_time():
time.sleep(2)
#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
def sleep_time():
time.sleep(2)
def count_time():
start_time = time.time()
sleep_time()
end_time = time.time()
use_time = end_time - start_time
print(f'函数sleep_time运行的时间是{use_time}')
if __name__ == '__main__':
count_time()
增加装饰器,函数count_sec就是一个装饰器,并且通过@语法糖使用装饰器,我们直接运行sleep_time函数,效果是和count_time函数是一样的。我们可以看到被装饰器修饰的函数,会被当作参数传入装饰器函数。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
def count_sec(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
use_time = end_time - start_time
print(f'{func.__name__}运行消耗的时间是{use_time}')
return wrapper
@count_sec
def sleep_time():
time.sleep(2)
def count_time():
start_time = time.time()
sleep_time()
end_time = time.time()
use_time = end_time - start_time
print(f'函数sleep_time运行的时间是{use_time}')
if __name__ == '__main__':
sleep_time()
二、被装饰函数带参数
修改sleep_time函数和装饰器函数,如下,运行后,效果是一样的。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
def count_sec(func):
def wrapper(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
use_time = end_time - start_time
print(f'{func.__name__}运行消耗的时间是{use_time}')
return wrapper
@count_sec
def sleep_time(sec):
time.sleep(sec)
if __name__ == '__main__':
sleep_time(2)
三、被装饰函数有返回值
再修改sleep_time函数和装饰器函数,如下,运行后,效果是一样的。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
def count_sec(func):
def wrapper(*args, **kwargs):
start_time = time.time()
return_value = func(*args, **kwargs)
end_time = time.time()
use_time = end_time - start_time
print(f'{func.__name__},{return_value}运行消耗的时间是{use_time}')
return return_value
return wrapper
@count_sec
def sleep_time(sec):
time.sleep(sec)
return "sleep end"
if __name__ == '__main__':
sleep_time(2)
四、装饰器带参数
要装饰器带参数,再包一层函数即可,如下
#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
def count_who_sleep(who):
def count_sec(func):
def wrapper(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
use_time = end_time - start_time
print(f'{who}睡觉,睡了多久{use_time}')
return wrapper
return count_sec
@count_who_sleep(who="dog")
def sleep_time(sec):
time.sleep(sec)
return "sleep end"
if __name__ == '__main__':
sleep_time(2)
除了函数装饰器,还有类装饰器,但是在这里就不分享,有兴趣的同学可以去了解下。今天就分享到这里,喜欢就点个关注吧,一起成长!