装饰器
装饰器的本身也是一个函数,它可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象,就是函数装饰函数的这样的一个过程。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
装饰器的形成
比如,测试一个函数的执行时间,在不改变原有代码的情况下,实现这个功能
简单装饰器
import time
def func1():
print('this is func1')
def timer(func):
def inner():
start = time.time()
func()
print(time.time() - start)
return inner
func1 = timer(func1)
func1()
但是这样还是有一个不好的地方,就是只要我们要实现这个功能,就有有这样一句话func1 = timer(func1),这样就会有点麻烦:就产生了一个叫语法糖的东东,是什么呢?
语法糖
import time
def timer(func):
def inner():
start = time.time()
func()
print(time.time() - start)
return inner
@timer #==> func1 = timer(func1)
def func1():
print('in func1')
func1()
带参数的装饰器
def timer(func):
def inner(a):
start = time.time()
func(a)
print(time.time() - start)
return inner
@timer
def func1(a):
print(a)
func1(1)
带动态参数的装饰器
import time
def wrapper(func):
def inner(*args, **kwargs):
start_time = time.localtime()
time_now = time.strftime("%Y-%m-%d %H:%M:%S", start_time)
with open('log', encoding='utf-8', mode='a') as f1:
f1.write("在%s是时间,执行了%s函数\n" % (time_now, func._name_))
ret = func(*args, **kwargs)
return ret
return inner()
@wrapper
def func1():
time.sleep(1)
print(555)
@wrapper
def func2():
time.sleep(2)
print(666)
func1()
func2()
查看函数信息的方法
def index():
'''这是一个主页信息'''
print('from index')
print(index.__doc__) #查看函数注释的方法
print(index.__name__) #查看函数名的方法
例如:
from functools import wraps
def demo(func):
@wraps(func) #@wraps要加载最内层函数的正上方
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@demo
def index():
'''你以为这是什么就是个注释而已'''
print('this is index')
print(index.__doc__)
print(index.__name__)
开放封闭的原则
装饰器遵循开放封闭的原则
1.对扩展是开放的,也就是说,必须允许代码扩展、添加新功能。
2.对修改是封闭的,尽可能的如果再次修改,不会影响别人的使用。
装饰器的主要功能和固定结构
'''装饰器的固定结构'''
def timer(func):
def inner(*args, **kwargs):
'''执行函数之前要做的'''
re = func(*args, **kwargs):
return re
'''wraps版'''
from functools import wraps
def demo(func):
@wraps(func) #@wraps要加载最内层函数的正上方
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
带参数的装饰器
def outer(flag):
def timer(func):
def inner(*args, **kwargs):
if flag:
print('执行函数之前要做的')
re = func(*args, **kwargs)
if flag:
print('执行函数之后要做的')
return re
return inner
return timer
@outer(False)
def func():
print('6666')
func()
多个装饰器装饰一个函数
def wrapper1(func):
def inner():
print('wrappers1,before func')
func()
print('wrappers1,after func')
return inner
def wrapper2(func):
def inner():
print('wrappers2,before func')
func()
print('wrappers2,after func')
return inner
@wrapper1
@wrapper2
def f():
print('in f')
f()