欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

python 装饰器3 九步入门2

shiping1 的头像

第六步:对参数数量不确定的函数进行装饰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -*- coding:gbk -*-
'''示例6: 对参数数量不确定的函数进行装饰,
参数用(*args, **kwargs),自动适应变参和命名参数'''
 
def deco(func):
    def _deco(*args, **kwargs):
        print("before %s called." % func.__name__)
        ret = func(*args, **kwargs)
        print("  after %s called. result: %s" % (func.__name__, ret))
        return ret
    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(1, 2)
myfunc(3, 4)
myfunc2(1, 2, 3)
myfunc2(3, 4, 5)

第七步:让装饰器带参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# -*- coding:gbk -*-
'''示例7: 在示例4的基础上,让装饰器带参数,
和上一示例相比在外层多了一层包装。
装饰函数名实际上应更有意义些'''
 
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")
def myfunc():
    print(" myfunc() called.")
 
@deco("module2")
def myfunc2():
    print(" myfunc2() called.")
 
myfunc()
myfunc2()

第八步:让装饰器带 类 参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# -*- coding:gbk -*-
'''示例8: 装饰器带类参数'''
 
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)
def myfunc():
    print(" myfunc() called.")
 
myfunc()
myfunc()

第九步:装饰器带类参数,并分拆公共类到其他py文件中,同时演示了对一个函数应用多个装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# -*- coding:gbk -*-
'''mylocker.py: 公共类 for 示例9.py'''
 
class mylocker:
    def __init__(self):
        print("mylocker.__init__() called.")
        
    @staticmethod
    def acquire():
        print("mylocker.acquire() called.")
        
    @staticmethod
    def unlock():
        print("  mylocker.unlock() called.")
 
class lockerex(mylocker):
    @staticmethod
    def acquire():
        print("lockerex.acquire() called.")
        
    @staticmethod
    def unlock():
        print("  lockerex.unlock() called.")
 
def lockhelper(cls):
    '''cls 必须实现acquire和release静态方法'''
    def _deco(func):
        def __deco(*args, **kwargs):
            print("before %s called." % func.__name__)
            cls.acquire()
            try:
                return func(*args, **kwargs)
            finally:
                cls.unlock()
        return __deco
    return _deco
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# -*- coding:gbk -*-
'''示例9: 装饰器带类参数,并分拆公共类到其他py文件中
同时演示了对一个函数应用多个装饰器'''
 
from mylocker import *
 
class example:
    @lockhelper(mylocker)
    def myfunc(self):
        print(" myfunc() called.")
 
    @lockhelper(mylocker)
    @lockhelper(lockerex)
    def myfunc2(self, a, b):
        print(" myfunc2() called.")
        return a + b
 
if __name__=="__main__":
    a = example()
    a.myfunc()
    print(a.myfunc())
    print(a.myfunc2(1, 2))
    print(a.myfunc2(3, 4))

下面是参考资料,当初有不少地方没看明白,真正练习后才明白些:

1. Python装饰器学习 http://blog.csdn.net/thy38/article/details/4471421

2. Python装饰器与面向切面编程 http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html

3. Python装饰器的理解 http://apps.hi.baidu.com/share/detail/17572338

分类: 编程笔记, Python
7
0
(请您对文章做出评价)
« 上一篇:插件框架精简版 x3py 已在Win/Mac/Linux下测试通过
» 下一篇:自动为py类的每个方法添加装饰器
posted @ 2011-12-21 10:30 张云贵 阅读(17678) 评论(6) 编辑 收藏

  
#1楼[楼主] 2011-12-21 15:45 张云贵  
1、对于装饰函数的最里层函数,最好再加上“@functools.wraps(func)”的修饰,这样就能保留原函数的特殊属性,例如:

import functools

def lockhelper(cls):
def _deco(func):
@functools.wraps(func)
def __deco(*args, **kwargs):

2、以上例子都是对每个函数单独进行包装,在待包装函数之前都有一个@,是否可以不在每个函数前都加修饰呢?下面这篇博文的末尾处介绍了一种自动遍历类的每个方法,自动为每个方法添加装饰:
http://blog.csdn.net/zylcf818/article/details/5342276
  
#2楼[楼主] 2011-12-21 17:03 张云贵  
我对自动批量添加装饰进行了试验,可支持多个装饰器,效果挺好:http://www.cnblogs.com/rhcad/archive/2011/12/21/2296063.html
  
#3楼 2012-09-25 14:40 zorro1x1  
学习学习!
  
#4楼 2013-03-05 09:50 w359405949  
少了“将类作为装饰器”这种用法
  
#5楼 2013-03-19 10:31 ZZB  
学习了,很不错的学习资料~
  
#6楼 2013-07-31 09:33 石大球球  
学习啦
来自 http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html
普通分类: