装饰器函数
#装饰器:在不改变函数的调用方式的情况下,给函数的前后添加新的功能。#
有的时候写完一段代码,过段时间需要对它进行升级、添加一些新功能,但是如果要直接修改原来的代码会影响其他人的调用,所以就需要一个不修改源代码且不修改原函数的调用方式的东西,又能为原函数增添新功能的东西,装饰器就是干这个的。(装饰器的本质其实是个闭包函数)
##复习:闭包;内部函数使用外部函数中的变量,这种情况下就称这是一个闭包。
def f1(b): def f2(): print(b) f2() return f2 ff=f1('bbb') ff() # bbb # bbb
####上例中timer()就是一个装饰器函数,f()就是被装饰函数
1)为什么要用装饰器
#开放封闭原则:对修改封闭,对扩展开放
2)什么是装饰器
装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。 强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式 装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
原则: 开放封闭原则
开放 : 对扩展是开放的
封闭 : 对修改是封闭
# timmer就是一个装饰器函数,对一个函数 有一些装饰作用
import time def timmer(f): #装饰器函数 def inner(): start = time.time() ret = f() #被装饰的函数 end = time.time() print(end - start) return ret return inner @timmer #语法糖 @装饰器函数名 def func(): #被装饰的函数 time.sleep(0.01) print('老板好同事好大家好') return '新年好' # func = timmer(func) ret = func() #inner() print(ret) ### 老板好同事好大家好 0.010995864868164062 新年好
3)装饰带参数函数的装饰器
import time def timmer(f): #装饰器函数 def inner(*args,**kwargs): #(1,2) /(1) start = time.time() ret = f(*args,**kwargs) #f(1,2) #被装饰的函数 end = time.time() print(end - start) return ret return inner @timmer #语法糖 @装饰器函数名 def func(a,b): #被装饰的函数 time.sleep(0.01) print('老板好同事好大家好',a,b) return '新年好' # func = timmer(func) ret = func(1,2) #inner() ret = func(1,b = 2) #inner() print(ret) ##### 老板好同事好大家好 1 2 0.030028820037841797 老板好同事好大家好 1 2 0.010994195938110352 新年好
4)装饰器的固定格式
def wrapper(f): #装饰器函数 def inner(*args,**kwargs): '''被装饰函数之前加的内容''' ret = f(*args,**kwargs) #被装饰的函数 '''被装饰函数之后加的内容''' return ret return inner @wrapper #语法糖 @装饰器函数名 def func(): #被装饰的函数 time.sleep(0.01) print('老板好同事好大家好') return '新年好' ret = func()
#温故而知新 def wrapper(func): def inner(*args,**kwargs): #接收参数时将参数聚合 inner((3)) print("在被装饰函数之前加的内容") ret = func(*args,**kwargs)#调用函数时将参数打散 holiday(*(3),**{}) print("在被装饰函数之后加的内容") return ret return inner @wrapper # holidy = wrapper(holiday) def holiday(day): print("全体放假%d天" %day) return "Happy!" ret = holiday(3) #inner(3)print(ret) #### 在被装饰函数之前加的内容 全体放假3天 在被装饰函数之后加的内容 Happy!
5) wraps
def span(): '''打印一个字符串的函数 ::return: ''' print("Python_Test!") print(span.__name__) # 查看字符串格式的函数名 print(span.__doc__) # document ####### span 打印一个字符串的函数 ::return:
##################################################
from functools import wraps #导入wraps装饰器 def wrapper(func): #func = holiday @wraps(func) def inner(*args,**kwargs): print('在被装饰的函数执行之前做的事') ret = func(*args,**kwargs) print('在被装饰的函数执行之后做的事') return ret return inner @wrapper #holiday = wrapper(holiday) def holiday(day): '''这是一个放假通知''' print('全体放假%s天'%day) return '好开心' print(holiday.__name__) #查看字符串格式的函数名 print(holiday.__doc__) #document ret = holiday(3) #inner print(ret)
###
holiday
这是一个放假通知
在被装饰的函数执行之前做的事
全体放假3天
在被装饰的函数执行之后做的事
好开心
###################################################
###三层装饰器
import time FLAG = False #定义全局变量 def timmer_out(flag): def timmer(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 timmer # timmer = timmer_out(FLAG) @timmer_out(FLAG) #wahaha = timmer(wahaha) def wahaha(): time.sleep(0.1) print('wahahahahahaha') @timmer_out(FLAG) def erguotou(): time.sleep(0.1) print('erguotoutoutou') wahaha() erguotou()
##温故而知新(带参数的装饰器)
import time FLAG = True def timmer_out(flag): def timmer(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 timmer @timmer_out(FLAG) def func1(): time.sleep(0.1) print("Happy1111") return "呵呵呵!!!" @timmer_out(FLAG) def func2(): time.sleep(0.1) print("Happy2222") return "哈哈哈!!!" func1() func2() ##### Happy1111 0.10094833374023438 Happy2222 0.1000070571899414
6)多个装饰器装饰同一个函数
def wrapper3(func): def inner3(): print("In wrapper3 ,before func") ret = func() print("In wrapper3 ,after func") return ret return inner3 @wrapper3 @wrapper2 @wrapper1 def f(): print("This is a f") return "万能装饰器!" print(f()) ########### In wrapper3 ,before func In wrapper2 ,before func In wrapper1 ,before func This is a f In wrapper1 ,after func In wrapper2 ,after func In wrapper3 ,after func 万能装饰器!