第一步:最简单的函数,准备附加额外功能
#-*-coding:gbk-*- '''示例1:最简单的函数,表示调用了两次''' defmyfunc(): print("myfunc()called.") myfunc() myfunc()
第二步:使用装饰函数在函数执行前和执行后分别附加额外功能
#-*-coding:gbk-*- '''示例2:替换函数(装饰) 装饰函数的参数是被装饰的函数对象,返回原函数对象 装饰的实质语句:myfunc=deco(myfunc)''' defdeco(func): print("beforemyfunc()called.") func() print("aftermyfunc()called.") returnfunc defmyfunc(): print("myfunc()called.") myfunc=deco(myfunc) myfunc() myfunc()
第三步:使用语法糖@来装饰函数
#-*-coding:gbk-*- '''示例3:使用语法糖@来装饰函数,相当于“myfunc=deco(myfunc)” 但发现新函数只在第一次被调用,且原函数多调用了一次''' defdeco(func): print("beforemyfunc()called.") func() print("aftermyfunc()called.") returnfunc @deco defmyfunc(): print("myfunc()called.") myfunc() myfunc()
相关推荐:《Python视频教程》
第四步:使用内嵌包装函数来确保每次新函数都被调用
#-*-coding:gbk-*- '''示例4:使用内嵌包装函数来确保每次新函数都被调用, 内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象''' defdeco(func): def_deco(): print("beforemyfunc()called.") func() print("aftermyfunc()called.") #不需要返回func,实际上应返回原函数的返回值 return_deco @deco defmyfunc(): print("myfunc()called.") return'ok' myfunc() myfunc()
第五步:对带参数的函数进行装饰
#-*-coding:gbk-*- '''示例5:对带参数的函数进行装饰, 内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象''' defdeco(func): def_deco(a,b): print("beforemyfunc()called.") ret=func(a,b) print("aftermyfunc()called.result:%s"%ret) returnret return_deco @deco defmyfunc(a,b): print("myfunc(%s,%s)called."%(a,b)) returna+b myfunc(1,2) myfunc(3,4)
第六步:对参数数量不确定的函数进行装饰
#-*-coding:gbk-*- '''示例6:对参数数量不确定的函数进行装饰, 参数用(*args,**kwargs),自动适应变参和命名参数''' defdeco(func): def_deco(*args,**kwargs): print("before%scalled."%func.__name__) ret=func(*args,**kwargs) print("after%scalled.result:%s"%(func.__name__,ret)) returnret return_deco @deco defmyfunc(a,b): print("myfunc(%s,%s)called."%(a,b)) returna+b @deco defmyfunc2(a,b,c): print("myfunc2(%s,%s,%s)called."%(a,b,c)) returna+b+c myfunc(1,2) myfunc(3,4) myfunc2(1,2,3) myfunc2(3,4,5)
第七步:让装饰器带参数
#-*-coding:gbk-*- '''示例7:在示例4的基础上,让装饰器带参数, 和上一示例相比在外层多了一层包装。 装饰函数名实际上应更有意义些''' defdeco(arg): def_deco(func): def__deco(): print("before%scalled[%s]."%(func.__name__,arg)) func() print("after%scalled[%s]."%(func.__name__,arg)) return__deco return_deco @deco("mymodule") defmyfunc(): print("myfunc()called.") @deco("module2") defmyfunc2(): print("myfunc2()called.") myfunc() myfunc2()
第八步:让装饰器带类参数
#-*-coding:gbk-*- '''示例8:装饰器带类参数''' classlocker: def__init__(self): print("locker.__init__()shouldbenotcalled.") @staticmethod defacquire(): print("locker.acquire()called.(这是静态方法)") @staticmethod defrelease(): print("locker.release()called.(不需要对象实例)") defdeco(cls): '''cls必须实现acquire和release静态方法''' def_deco(func): def__deco(): print("before%scalled[%s]."%(func.__name__,cls)) cls.acquire() try: returnfunc() finally: cls.release() return__deco return_deco @deco(locker) defmyfunc(): print("myfunc()called.") myfunc() myfunc()
第九步:装饰器带类参数,并分拆公共类到其他py文件中,同时演示了对一个函数应用多个装饰器。
#-*-coding:gbk-*- '''mylocker.py:公共类for示例9.py''' classmylocker: def__init__(self): print("mylocker.__init__()called.") @staticmethod defacquire(): print("mylocker.acquire()called.") @staticmethod defunlock(): print("mylocker.unlock()called.") classlockerex(mylocker): @staticmethod defacquire(): print("lockerex.acquire()called.") @staticmethod defunlock(): print("lockerex.unlock()called.") deflockhelper(cls): '''cls必须实现acquire和release静态方法''' def_deco(func): def__deco(*args,**kwargs): print("before%scalled."%func.__name__) cls.acquire() try: returnfunc(*args,**kwargs) finally: cls.unlock() return__deco return_deco
#-*-coding:gbk-*- '''示例9:装饰器带类参数,并分拆公共类到其他py文件中 同时演示了对一个函数应用多个装饰器''' frommylockerimport* classexample: @lockhelper(mylocker) defmyfunc(self): print("myfunc()called.") @lockhelper(mylocker) @lockhelper(lockerex) defmyfunc2(self,a,b): print("myfunc2()called.") returna+b if__name__=="__main__": a=example() a.myfunc() print(a.myfunc()) print(a.myfunc2(1,2)) print(a.myfunc2(3,4))
相关推荐: