装饰器:
一、装饰器的形成过程
1、阶段一:需求一:需要给函数加上另外一个功能且不能改变原函数
import time
def func():
time.sleep(1)
def timer(f):
start = time.time()
f()
end = time.time()
print(end-start)
timer(func)
2、阶段二:需求二:在需求一的基础上,不改变函数的调用方式
import time
def func():
time.sleep(1)
def timer(f): # 装饰器函数
def inner(): # 利用函数的闭包解决调用问题
start = time.time()
f() # 被装饰的函数
end = time.time()
print(end-start)
return inner
func = timer(func)
func()
3、阶段三:需求三:在前两个需求的基础上,被装饰的函数有参数和返回值
import time
def timer(f):
def inner(*args, **kwargs):
start = time.time()
ret = f(*args, **kwargs)
end = time.time()
print(end-start)
return ret
return inner
@timer # 语法糖 相当于func = timer(func)
def func():
time.sleep(1)
# func = timer(func)
func()
4、最终格式:
def wrapper(func):
def inner(*args, **kwargs):
print('装饰前做的事')
ret = func(*args, **kwargs) # 被装饰的函数
print('装饰后做的事')
return ret
return inner
5、解决print(func.__name__)改变原函数名问题
from functools import wraps
def timer(f):
@wraps(func) # 给内函数加一个装饰器
def inner(*args, **kwargs):
start = time.time()
ret = f(*args, **kwargs)
end = time.time()
print(end-start)
return ret
return inner
给内函数加一个装饰器,这样在调用print(func.__name__)的时候不改变原函数名
6、带参数的装饰器:需求扩展:假如1万个函数加装饰器,一次控制装饰器执行或者不执行。
import time
FLAG = True
def timer_out(flag):
def timer(f):
def inner(*args, **kwargs):
if flag:
start = time.time()
ret = f(*args, **kwargs)
end = time.time()
print(end-start)
else:
ret = f(*args, **kwargs)
return ret
return inner
return timer
@timer_out(FLAG) # 传参数装饰,代表
def func():
time.sleep(1)
print('石谦')
func()
7、多个装饰器装饰一个函数
套娃模式执行
def wrapper1(f):
def inner(*args, **kwargs):
print('wrapper1 before')
ret = f(*args, **kwargs)
print('wrapper1 end')
return ret
return inner
def wrapper2(f):
def inner(*args, **kwargs):
print('wrapper2 before')
ret = f(*args, **kwargs)
print('wrapper2 end')
return ret
return inner
@wrapper1
@wrapper2
def func():
print('shiqian')
func()
二、开放封闭原则
开放:对扩展是开放的
修改:对修改是封闭的