一、装饰函数和方法
1.对不带参数的函数进行装饰
'''对不带参数的函数进行装饰 deco1.py''' def deco(func): def _deco(): print('before %s() called.' % func.__name__) func() print('after %s() called.' % func.__name__) return _deco # myFunc = deco(myFunc) @deco def myFunc(): print('myFunc() called.') myFunc() myFunc()
运行结果:
before myFunc() called.
myFunc() called.
after myFunc() called.
before myFunc() called.
myFunc() called.
after myFunc() called.
2.对带参数的函数进行装饰
'''对带参数的函数进行装饰 deco2.py''' def deco(func): def _deco(a, b): print('before %s() called.' % func.__name__) re = func(a, b) print('after %s() called. result: %s' % (func.__name__, re)) return re return _deco @deco def myFunc(x, y): print('myFunc(%s, %s) called.' % (x, y)) return x + y print(myFunc(2, 8)) print(myFunc(9, 9))
运行结果:
before myFunc() called. myFunc(2, 8) called. after myFunc() called. result: 10 10 before myFunc() called. myFunc(9, 9) called. after myFunc() called. result: 18 18
3.对有可变参数的函数进行装饰
'''对有可变参数的函数进行装饰 deco3.py''' def deco(func): def _deco(*args, **kwargs): print('before %s() called.' % func.__name__) re = func(*args, **kwargs) print('after %s() called. result: %s' % (func.__name__, re)) return re return _deco @deco def myFunc(a, b): print('myFunc(%s, %s) called.' % (a, b)) return a + b @deco def myFunc2(a, b, c): print('myFunc2(%s, %s, %s) called.' % (a, b, c)) return a + b + c myFunc(2, 8) myFunc(9, 9) myFunc2(1, 2, 3) myFunc2(4, 5, 6)
运行结果:
before myFunc() called. myFunc(2, 8) called. after myFunc() called. result: 10 before myFunc() called. myFunc(9, 9) called. after myFunc() called. result: 18 before myFunc2() called. myFunc2(1, 2, 3) called. after myFunc2() called. result: 6 before myFunc2() called. myFunc2(4, 5, 6) called. after myFunc2() called. result: 15
4.带参数的装饰器
'''带参数的装饰器 deco4.py''' def deco(arg): def _deco(func): def __deco(): print('before %s called [%s].' % (func.__name__, arg)) func() print('after %s called [%s].' % (func.__name__, arg)) return __deco return _deco @deco('myModule') #myFunc = deco('myModule')(myFunc) def myFunc(): print('myFunc() called.') @deco('myModule2') def myFunc2(): print('myFunc2() called.') myFunc() myFunc2()
运行结果:
before myFunc called [myModule].
myFunc() called.
after myFunc called [myModule].
before myFunc2 called [myModule2].
myFunc2() called.
after myFunc2 called [myModule2].
5.带类参数的装饰器
'''带类参数的装饰器 deco5.py''' class locker: def __init__(self): print('locker.__init__() should be not called.') @staticmethod def acquire(): print('locker.acquire() called.(这是静态方法)') @staticmethod def release(): print('locker.release() called.(不需要对象实例)') def deco(cls): '''cls 必须实现acquire和release静态方法''' def _deco(func): def __deco(): print('before %s called [%s].' % (func.__name__, cls)) cls.acquire() try: return func() finally: cls.release() return __deco return _deco @deco(locker) #myFunc = deco(locker)(myFunc) def myFunc(): print('myFunc() called.') myFunc() myFunc()
运行结果:
before myFunc called [<class '__main__.locker'>]. locker.acquire() called.(这是静态方法) myFunc() called. locker.release() called.(不需要对象实例) before myFunc called [<class '__main__.locker'>]. locker.acquire() called.(这是静态方法) myFunc() called. locker.release() called.(不需要对象实例)
6.带类参数的装饰器,对一个函数应用多个装饰器
1 '''装饰器公共类 deco6.py''' 2 3 class mylocker: 4 def __init__(self): 5 print('mylocker.__init__() called.') 6 7 @staticmethod 8 def acquire(): 9 print('mylocker.acquire() called.') 10 11 @staticmethod 12 def release(): 13 print('mylocker.release() called.') 14 15 class lockerex(mylocker): 16 @staticmethod 17 def acquire(): 18 print('lockerex.acquire() called.') 19 20 @staticmethod 21 def release(): 22 print('lockerex.release() called.') 23 24 def lockhelper(cls): 25 '''cls必须实现acquire和release静态方法''' 26 def _deco(func): 27 def __deco(*args, **kwargs): 28 print('before %s called. [%s]' % (func.__name__, cls)) 29 cls.acquire() 30 try: 31 return func(*args, **kwargs) 32 finally: 33 cls.release() 34 return __deco 35 return _deco
1 '''测试一个函数对应多个装饰器 deco6.py''' 2 from deco6 import * 3 4 class example: 5 #myFunc = lockhelper(mylocker)(myFunc) 6 @lockhelper(mylocker) 7 def myFunc(self): 8 print('myFunc() called.') 9 10 #myFunc2 = lockhelper(mylocker)(lockhelper(lockerex)(myFunc2)) 11 @lockhelper(mylocker) 12 @lockhelper(lockerex) 13 def myFunc2(self, a, b): 14 print('myFunc2() called.') 15 return a + b 16 17 if __name__ == '__main__': 18 a = example() 19 a.myFunc() 20 print(a.myFunc()) 21 print('============================') 22 print(a.myFunc2(1, 2)) 23 print(a.myFunc2(3, 5))
运行结果:
before myFunc called. [<class 'deco6.mylocker'>] mylocker.acquire() called. myFunc() called. mylocker.release() called. before myFunc called. [<class 'deco6.mylocker'>] mylocker.acquire() called. myFunc() called. mylocker.release() called. None ============================ before __deco called. [<class 'deco6.mylocker'>] mylocker.acquire() called. before myFunc2 called. [<class 'deco6.lockerex'>] lockerex.acquire() called. myFunc2() called. lockerex.release() called. mylocker.release() called. 3 before __deco called. [<class 'deco6.mylocker'>] mylocker.acquire() called. before myFunc2 called. [<class 'deco6.lockerex'>] lockerex.acquire() called. myFunc2() called. lockerex.release() called. mylocker.release() called. 8
二、装饰类
以上的例子中,装饰器接收一个函数,并返回一个函数,从而起到加工函数的效果(装饰器(如deco中)新建了一个可调用对象(如_deco),在其中添加了新增的功能print,通过调用原有函数return myFunc()来实现原有函数的功能,最后将新建的调用对象返回return _deco)。
在Python 2.6以后,装饰器被拓展到类。一个装饰器可以接收一个类,并返回一个类,从而起到加工类的效果。
def deco(aClass): class newClass: def __init__(self, age): self.total_display = 0 self.wrapped = aClass(age) def display(self): self.total_display += 1 # 记录display方法的调用次数 print('total display', self.total_display) self.wrapped.display() return newClass @deco # Bird = deco(Bird) class Bird: def __init__(self, age): self.age = age def display(self): print('My age is', self.age) b = Bird(5) for i in range(3): b.display()
运行结果:
total display 1 My age is 5 total display 2 My age is 5 total display 3 My age is 5