一、装饰器的目的
我们需要遵守开放封闭原则。
开放封闭原则:程序上线以后就应该对修改封闭,对扩展开放
修改封闭:不能修改功能性函数的源代码
不能修改功能性函数的调用方式
二、装饰器的逐步实现
首先,我们定义一个函数
import time, random def msg(): print('I have something to tell you, please wait a moment.') time.sleep(random.randint(1, 5)) print('I like you.') msg()
该函数会随机休眠1-5秒钟。
现在,我们想要给该函数增加一个计时的功能,看看函数具体运行了多久。
扫描二维码关注公众号,回复:
4779082 查看本文章
import time, random def msg(): print('I have something to tell you, please wait a moment.') time.sleep(random.randint(1, 5)) print('I like you.') start_time = time.time() msg() stop_time = time.time() print('Run time is %s' % (stop_time - start_time))
并且如果要重复使用计时功能,就要写重复代码,所以我们想到了将计时功能封装成一个函数
def wrapper(): start = time.time() msg() stop = time.time() print('Run time is %s' % (stop - start)) wrapper()
我们将wrapper函数写死了,只能对内部调用的msg函数进行计时,使用闭包函数
def timmer(func): def wrapper(): start = time.time() func() stop = time.time() print('Run time is %s' % (stop - start)) return wrapper # 将wrapper函数的内存地址作为返回值返回。 msg = timmer(msg) # 作为参数的msg是我们定义的msg函数的内存地址 # 作为变量名的msg是指向wrapper函数的内存地址
这样子我们就实现了偷梁换柱,在外观上没有更改msg函数的调用方式。
当传入的函数有参数或者有返回值时
def timmer(func): def wrapper(*args, **kwargs): strat_time = time.time() res = func(*args, **kwargs) stop_time = time.time() return res return wrapper
装饰器的使用方法:语法糖
import time, random def timmer(func): def wrapper(*args, **kwargs): strat_time = time.time() res = func(*args, **kwargs) stop_time = time.time() return res return wrapper @timmer def msg(): print('I have something to tell you, please wait a moment.') time.sleep(random.randint(1, 5)) print('I like you.') msg()
含参装饰器,含参装饰器是一个三层的闭包函数
import time def timemer(partment): def func(func_1): def wrapper(*args,**wkargs): if partment=='task1': start = time.time() func_1(*args, **wkargs) stop = time.time() print("the task1 run time is :", stop - start) elif partment=='task2': start = time.time() func_1(*args, **wkargs) stop = time.time() print("the task2 run time is :", stop - start) return wrapper return func @timemer(partment='task1') def task1(): time.sleep(2) print("in the task1") @timemer(partment='task2') def task2(): time.sleep(2) print("in the task2") task1() task2()
类实现的含参装饰器
from functools import wraps
class decorate: def __init__(self, name): self.name = name # 装饰器的参数
def __call__(self, func): @wraps(func) def deco(*args, **kwargs): if self.name == 'Admin': passelif self.name == 'Student': passelif self.name == 'Teacher': passreturn func(*args, **kwargs) return deco
@decarate('Admin')