一、装饰器出现的背景:
对前面已经投入生成的程序(由函数构成)进行扩展,但是不能改变原先函数的源码以及调用方式。
二、源码
1、decorator1.py
#现在要给每个函数添加一个功能:显示每个函数的执行时间,但是每个函数的源码不能改变,以及每个函数的调用方式不能改变。 #(试想你的雇主用了你的第一版函数,想试试第二版,但调用的地方太多了,如果一一改变,太麻烦) #那么装饰器是个不错的选择 import time # def addRunTime(func): # # startTime = time.time() # func() # endTime=time.time() # print(‘time is %f‘ % (endTime-startTime)) # return func def addRunTime(func): #这个函数的取名和你要添加的功能有关 def decorator(): #注意这个子函数,和上一版(已经注释了的)的区别 #print(decorator) #print(func) startTime = time.time() func() endTime=time.time() print(‘the running time of ‘ + func.__name__ + ‘ is %f‘ % (endTime - startTime)) return decorator @addRunTime #等价与 function1=addRunTime(function1) def function1(): time.sleep(1); print(‘in the function1‘) @addRunTime def function2(): time.sleep(1); print(‘in the function2‘) function1() ‘‘‘ 执行流程:addRunTime(function1) ‘‘‘ function2()
2、decorator2.py
‘‘‘ 给带有形参的函数扩展功能:这里在decorator1的基础上,给每个函数添加参数 ‘‘‘ import time def addRunTime(func): def decorator(*args,**kwargs): #实参实际传入到这个函数 #print(decorator) # print(func) startTime = time.time() func(*args,**kwargs) endTime=time.time() print(‘the running time of ‘+func.__name__+‘ is %f‘ % (endTime-startTime)) return decorator @addRunTime def function1(arg1): time.sleep(1); print("in the function1 arg1=",arg1) # arg1+**kaargs 函数调用的时候,参数必须使用 “arg1="shabi1",arg2="shabi2",arg3=‘shabi3‘”形式给出 #且第一个实参 必须是arg1=xxx ,函数会把第一个参数赋值给arg1,其余的参数放在一个字典的形式给kwargs @addRunTime def function2(arg1,*args): time.sleep(1); print("in the function2 arg1=%s,args=%s" %(arg1,args)) #*args,**kwargs,函数调用的时候,参数可以是任意数字,字符串,列表,字典,元组的组成,key=value的实参必须放在最后面 #函数会把所有的非 key=value的放在一个元组里面传给args,而把所有的key=value参数放在一个字典里面传给kwargs @addRunTime def function3(*args,**kwargs): time.sleep(1); print("in the function3 args=%s,kwargs=%s" %(args,kwargs)) function1(‘shabi1‘) function2(‘shabi2‘,‘shabi3‘) function3(1,2,[3,4],arg1=‘shabi1‘,arg2=‘shabi2‘)
3、decorator3.py
‘‘‘ 是否扩展可以选择(可以扩展,也可以不扩展):这里在decorator2的基础上,通过ifAdd的值来确定是否扩展功能 ‘‘‘ import time def ifAddRunTime(ifAdd): def addRunTime(func): def decorator(*args,**kwargs): if ifAdd==True: startTime = time.time() func(*args,**kwargs) endTime=time.time() print(‘the running time of ‘+func.__name__+‘ is %f‘ % (endTime-startTime)) else: func(*args, **kwargs) return decorator return addRunTime #这个return 别忘了, 记住语法糖的等价形式, 如果没有返回值,会报错 @ifAddRunTime(True) def function1(arg1): time.sleep(1); print("in the function1 arg1=",arg1) @ifAddRunTime(False) def function2(arg1,*args): time.sleep(1); print("in the function2 arg1=%s,args=%s" %(arg1,args)) @ifAddRunTime(True) def function3(*args,**kwargs): time.sleep(1); print("in the function3 args=%s,kwargs=%s" %(args,kwargs)) #现在要给每个函数添加一个功能:显示每个函数的执行时间,但是每个函数的调用方式不能改变。(试想你的雇主用了你的第一版函数,想试试第二版,但调用的地方太多了,如果一一改变,太麻烦) #那么装饰器是个不错的选择 function1(‘shabi1‘) function2(‘shabi2‘,‘shabi3‘) function3(1,2,[3,4],arg1=‘shabi1‘,arg2=‘shabi2‘)
4、decorator4.py
‘‘‘ 保留函数的返回值,这里是在decorator3的基础上,保留了函数的返回值 ‘‘‘ import time def ifAddRunTime(ifAdd): def addRunTime(func): def decorator(*args,**kwargs): if ifAdd==True: startTime = time.time() funcValue=func(*args,**kwargs) endTime=time.time() print(‘the running time of ‘+func.__name__+‘ is %f‘ % (endTime-startTime)) return funcValue else: return func(*args, **kwargs) return decorator return addRunTime #这个return 别忘了, 记住语法糖的等价形式, 如果没有返回值,会报错 @ifAddRunTime(True) def function1(arg1): time.sleep(1); print("in the function1 arg1=",arg1) return 1 @ifAddRunTime(False) def function2(arg1,*args): time.sleep(1); print("in the function2 arg1=%s,args=%s" %(arg1,args)) return 2 @ifAddRunTime(True) def function3(*args,**kwargs): time.sleep(1); print("in the function3 args=%s,kwargs=%s" %(args,kwargs)) return 3 #现在要给每个函数添加一个功能:显示每个函数的执行时间,但是每个函数的调用方式不能改变。(试想你的雇主用了你的第一版函数,想试试第二版,但调用的地方太多了,如果一一改变,太麻烦) #那么装饰器是个不错的选择 print(function1(‘shabi1‘)) function2(‘shabi2‘,‘shabi3‘) function3(1,2,[3,4],arg1=‘shabi1‘,arg2=‘shabi2‘)