装饰器(语法糖)
装饰器的本质:一个闭包函数
装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
例子1.
给hahaha函数加上一个timmer(计算函数执行时间)的功能。
import time def timmer(func): #函数名可以当做函数的参数 def inner(): start = time.time() func() end = time.time() print(start - end) return inner # 语法糖 @timmer # @把hahaha函数名作为参数传到timmer(),执行了一次, 然后进行了重新赋值 hahaha = timmer(hahaha) --> inner() def hahaha(): time.sleep(0.1) print('aaaa') # time(hahaha) 不能改变这个函数的调用方式 # 也不能修改源代码 # hahaha = timmer(hahaha) timmer(hahaha)函数的执行结果返回 inner函数的内存地址,然后赋值给hahaha # hahaha() 就等同于 inner() hahaha()
装饰器的设计模式:开放封闭原则
开放:对扩展是开放的
封闭:对修改是封闭的
刚刚我们讨论的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办?
import time def timer(func): def inner(*args, **kwargs): start_time = time.time() func(*args, **kwargs) end_time = time.time() print(end_time - start_time) return inner @timer def func1(a): time.sleep(2) print(a) func1('bb')
带参数的装饰器
def outer(flag): def timer(func): def inner(*args, **kwargs): if flag: print('执行函数之前要做的') func(*args, **kwargs) if flag: print('执行函数之后要做的') return inner return timer @outer(True) def func2(mode): print(111, mode) func2('rrr')
多个装饰器装饰同一个函数
有些时候,我们也会用到多个装饰器装饰同一个函数的情况。
def wrapper1(func): def inner(): print('wrapper1 ,before func') func() print('wrapper1 ,after func') return inner def wrapper2(func): def inner(): print('wrapper2 ,before func') func() print('wrapper2 ,after func') return inner @wrapper2 @wrapper1 def f(): print('in f') f()
输出:
wrapper2 ,before func wrapper1 ,before func in f wrapper1 ,after func wrapper2 ,after func