装饰器函数
#装饰器:在不改变函数的调用方式的情况下,给函数的前后添加新的功能。#
有的时候写完一段代码,过段时间需要对它进行升级、添加一些新功能,但是如果要直接修改原来的代码会影响其他人的调用,所以就需要一个不修改源代码且不修改原函数的调用方式的东西,又能为原函数增添新功能的东西,装饰器就是干这个的。(装饰器的本质其实是个闭包函数)
##复习:闭包;内部函数使用外部函数中的变量,这种情况下就称这是一个闭包。
def f1(b): def f2(): print(b) f2() return f2ff=f1('bbb')ff()# bbb# bbb
####上例中timer()就是一个装饰器函数,f()就是被装饰函数
1)为什么要用装饰器
#开放封闭原则:对修改封闭,对扩展开放
2)什么是装饰器
装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
原则: 开放封闭原则
开放 : 对扩展是开放的 封闭 : 对修改是封闭
# timmer就是一个装饰器函数,对一个函数 有一些装饰作用
import timedef 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 timedef 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 20.030028820037841797老板好同事好大家好 1 20.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__) #documentret = holiday(3) #innerprint(ret) ###
holiday
这是一个放假通知在被装饰的函数执行之前做的事全体放假3天在被装饰的函数执行之后做的事好开心###################################################
###三层装饰器
import timeFLAG = 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 timeFLAG = Truedef 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()#####Happy11110.10094833374023438Happy22220.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@wrapper1def f(): print("This is a f") return "万能装饰器!"print(f())###########In wrapper3 ,before funcIn wrapper2 ,before funcIn wrapper1 ,before funcThis is a fIn wrapper1 ,after funcIn wrapper2 ,after funcIn wrapper3 ,after func万能装饰器!