python装饰器函数
1.装饰器函数引导
功能:计算函数执行时长
import time """ 方式一: 函数首位添加时间,差值就是函数执行时间 缺点:每个函数都要加上,工作量大 """ def f1(): start_time = time.time() print("f1 excute") end_time = time.time() print(end_time-start_time) f1()
import time """ 方式二: 调用函数前后 缺点:调用函数前后都要加,别人引用的也要加 """ def f1(): print("f1 excute") start_time = time.time() f1() end_time = time.time() print(end_time - start_time)
import time """ 方式三: 写个计算函数执行时间函数 缺点:改变了函数的调用方式 """ def f1(): print("f1 excute") def timer(func): start_time = time.time() func end_time = time.time() print(end_time - start_time) timer(f1())
想要不改变调用方式的前提下完成该功能
import time """ 方式四: 缺点:还要复制操作 """ def f1(): print("f1 excute") def timer(func): def inner(): start_time = time.time() func end_time = time.time() print(end_time - start_time) return inner f1 = timer(f1()) f1()
直接将赋值操作替换
import time def timer(func): def inner(): start_time = time.time() func() end_time = time.time() print(end_time - start_time) return inner @timer def f1(): print("f1 excute") f1()
总结:
装饰器的本质:一个闭包函数
装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
#带参数
import time def timer(func): def inner(a): start = time.time() func(a) print(time.time() - start) return inner @timer def f1(a): print(a) f1(1)
# 带返回值 import time def timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner @timer #==> func1 = timer(func1) def func1(a,b): print('in func1') @timer #==> func2 = timer(func2) def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over' func1('aaaaaa','bbbbbb') print(func2('aaaaaa'))
import time def timer(func): def inner(*args, **kwargs): start = time.time() re = func(*args, **kwargs) print(time.time() - start) return re return inner @timer # ==> func1 = timer(func1) def f1(a, b): print('f1 excute ,a=%s,b=%s' % (a, b)) @timer # ==> func2 = timer(func2) def f2(a): print(a) return 'f2 over' f1('x1', 'x2') a = f2('a') print(a) # f1 excute ,a=x1,b=x2 # 0.0 # a # 0.0 # f2 over
import time # from functools import wraps def timer(func): # @wraps(func) # 防止查看函数注释失效 def inner(*args, **kwargs): start = time.time() re = func(*args, **kwargs) print(time.time() - start) return re return inner @timer # ==> func1 = timer(func1) def f1(a, b): """f1函数注释""" print('f1 excute ,a=%s,b=%s' % (a, b)) @timer # ==> func2 = timer(func2) def f2(a): """f2函数注释""" print(a) return 'f2 over' print(f1.__doc__) # 查看函数注释 None print(f1.__name__) # 查看函数名称 inner
正常情况:
def demo(): """函数注释""" print("a") print(demo.__doc__) # 查看函数注释 函数注释 print(demo.__name__) # 查看函数名称 demo
为防止失效:
import time from functools import wraps def timer(func): @wraps(func) # 防止查看函数注释失效 def inner(*args, **kwargs): start = time.time() re = func(*args, **kwargs) print(time.time() - start) return re return inner @timer # ==> func1 = timer(func1) def f1(a, b): """f1函数注释""" print('f1 excute ,a=%s,b=%s' % (a, b)) @timer # ==> func2 = timer(func2) def f2(a): """f2函数注释""" print(a) return 'f2 over' print(f1.__doc__) # 查看函数注释 f1函数注释 print(f1.__name__) # 查看函数名称 f1
2.开放封闭原则
1.对扩展是开放的 我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。 2.对修改是封闭的 就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则
3.装饰器的主要功能和装饰器的固定结构
装饰器的主要功能:在不修改原函数的调用方式的基础上,在函数前后添加功能,实现功能扩展
from functools import wraps def demo(func): @wraps(func) # 防止查看函数注释等方法失效 def inner(*args, **kwargs): """调用函数前要实现的功能""" re = func(*args, **kwargs) """调用函数后要实现的功能""" return re return inner
4.带参数的装饰器
使用参数控制装饰器的使用与否:在后面再嵌套一层
from functools import wraps def outer(flag): def demo(func): @wraps(func) def inner(*args, **kwargs): if flag: print("函数调用前") re = func(*args, **kwargs) if flag: print("函数调用后") return re return inner return demo @outer(False) def f1(): print("f1 execute") f1()
多个装饰器装饰同一个函数
from functools import wraps def timer1(func): @wraps(func) def inner(*args, **kwargs): print('''timer1执行函数之前要做的''') re = func(*args, **kwargs) print('''timer1执行函数之后要做的''') return re return inner def timer2(func): @wraps(func) def inner(*args, **kwargs): print('''timer2执行函数之前要做的''') re = func(*args, **kwargs) print('''timer2执行函数之后要做的''') return re return inner @timer1 @timer2 def func(): print(111) func() # timer1执行函数之前要做的 # timer2执行函数之前要做的 # 111 # timer2执行函数之后要做的 # timer1执行函数之后要做的