装饰器
Posted wanglan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰器相关的知识,希望对你有一定的参考价值。
装饰器的功能:在不修改原函数和其调用方式的情况下对原函数功能进行扩展
装饰器的本质是闭包函数
求一个函数的运行时间
import time def func(): start = time.time() print(‘老板好!同事好!大家好!‘) time.sleep(0.01) end = time.time() print(end-start ) func()
但是有多个函数都需要添加此功能时,就会显得很繁琐,此时可以写一个时间函数
import time def timer(f): start = time.time() f() time.sleep(0.01) end = time.time() print(end - start) def func(): print(‘老板好!同事好!大家好!‘) timer(func)
这样不管多少函数都可以调用这个时间函数来计算执行的时间了,但是这样改变了函数的调用方式,原本调用func函数的程序现在要改为调用timer了
import time def timer(f): start = time.time() f() time.sleep(0.01) end = time.time() print(end - start) def func(): print(‘老板好!同事好!大家好!‘) func = timer func()
这样修改很完美,但是timer函数需要一个参数,如果在赋值的时候传参, func = timer(func),timer函数就直接执行了,并不能实现
简单的装饰器实现上面的功能
import time def timer(f): #装饰器函数 def inner(): start = time.time() f() #被装饰的函数 time.sleep(0.01) end = time.time() print(end - start) return inner def func(): print(‘老板好!同事好!大家好!‘) func = timer(func) func()
语法糖
import time def timer(f): def inner(): start = time.time() f() time.sleep(0.01) end = time.time() print(end - start) return inner @timer # 语法糖 相当于func = timer(func) def func(): print(‘老板好!同事好!大家好!‘) # func = timer(func) func()
被装饰的函数有返回值
import time def timer(f): def inner(): start = time.time() ret = f() time.sleep( 0.01) end = time.time() print(end - start) return ret return inner @timer # 语法糖 相当于func = timer(func) def func(): print(‘老板好!同事好!大家好!‘) return ‘新年好‘ # func = timer(func) ret = func() print(ret)
带有参数的被装饰的函数
import time def timer(f): def inner(*args,**kwargs): start = time.time() ret = f(*args,**kwargs) time.sleep( 0.01) end = time.time() print(end - start) return ret return inner @timer # 语法糖 相当于func = timer(func) def func(a,b,c): print(‘老板好!同事好!大家好!‘,a,b,c) return ‘新年好‘ # func = timer(func) ret = func(1,2,c=3) #inner print(ret)
装饰器的固定模式
def wrapper(f): # f :被装饰的函数 def inner(*args, **kwargs): # 在被装饰函数之前要做的事 ret = f(*args, **kwargs) # 在被装饰函数之后要做的事 return ret return inner @wrapper # 语法糖 @装饰器的函数名 def func(a, b, c): # 被装饰的函数 print(a, b, c) return ‘新年好‘ ret = func(1, 2, c=3) print(ret)
查看函数信息的一些方法
def index(): ‘‘‘这是一个主页信息‘‘‘ print(‘from index‘) print(index.__doc__) #查看函数注释的方法 print(index.__name__) #查看函数名的方法
查看函数的信息
为函数添加了装饰器,在打印被装饰函数的__name__或__doc__的时候,打印的是装饰器的
def wrapper(f): # f :被装饰的函数 def inner(*args, **kwargs): # 在被装饰函数之前要做的事 ret = f(*args, **kwargs) # 在被装饰函数之后要做的事 return ret return inner @wrapper # 语法糖 @装饰器的函数名 def func(a, b, c): # 被装饰的函数 print(a, b, c) return ‘新年好‘ print(func.__name__) 打印结果: inner
想要打印被装饰的函数__name__或__doc__,可以使用wraps装饰器
from functools import wraps def wrapper(f): # f :被装饰的函数 @wraps(f) #f:被装饰的函数 def inner(*args, **kwargs): # 在被装饰函数之前要做的事 ret = f(*args, **kwargs) # 在被装饰函数之后要做的事 return ret return inner @wrapper # 语法糖 @装饰器的函数名 def func(a, b, c): # 被装饰的函数 print(a, b, c) return ‘新年好‘ print(func.__name__) 打印结果: func
带参数的装饰器
import time FLAG = True def timer_out(flag): def timer(func): def inner(*args, **kwargs): if flag: start = time.time() ret = func(*args, **kwargs) end = time.time() print(end - start) return ret else: ret = func(*args, **kwargs) return ret return inner return timer @timer_out(FLAG) def beibingyang(): time.sleep(0.1) print(‘beibingyang‘) @timer_out(FLAG) def erguotou(): time.sleep(0.1) print(‘erguotou‘) beibingyang() erguotou()
@timer_out(FLAG) 分为两部分:
@:为一部分
timer_out(FLAG):为一部分
timer_out(FLAG)执行时返回inner,此时@timer_out(FLAG)为@inner
@inner 为 beibingyang= timmer(beibingyang)
当FLAG改为False装饰器就失效了,这样添加和取消都比较便捷
多个装饰器装饰同一个函数
def wrapper1(func): #第一步执行后 func=f def inner1(): print(‘wrapper1 ,before func‘) #第六步 输出 wrapper1 ,before func func() #第七步 调用 f print(‘wrapper1 ,after func‘) #第八步 输出 wrapper1 ,before func return inner1 def wrapper2(func): #第二部执行后 func=inner1 def inner2(): print(‘wrapper2 ,before func‘) # 第四步 输出 wrapper2 ,before func func() #第五部 调用inner1 print(‘wrapper2 ,after func‘) #第九步 输出 wrapper2 ,before func return inner2 @wrapper2 #第二步执行 f=wrapper2(f) 返回inner2 f=inner2 @wrapper1 #第一步执行 f=wrapper1(f) 返回 inner1 f=inner1 def f(): print(‘in f‘) f() #第三步执行 f() 此时f为inner2 调用inner2
打印结果
wrapper2 ,before func wrapper1 ,before func in f wrapper1 ,after func wrapper2 ,after func
以上是关于装饰器的主要内容,如果未能解决你的问题,请参考以下文章