一、装饰函数和方法

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

 

posted on 2013-05-17 01:11  101010  阅读(401)  评论(0编辑  收藏  举报