python 装饰器

2. 装饰器语法
(1)无参数装饰器
def deco(func):  
    print func  
    return func  
@deco  
def foo():pass  
foo() 
第一个函数deco是装饰函数,它的参数就是被装饰的函数对象.我们可以在deco函数内对传入的函数对象做一番"装饰”,然后返回这个对象(但一定要返回,不然外面调用foo的地方将会无函数可用.实际上此时foo=deco(foo)).
(2)有参数装饰器
def decomaker(arg):  
    '通常对arg会有一定的要求'  
    """由于有参数的decorator函数在调用时只会使用应用时的参数  
       而不接收被装饰的函数做为参数,所以必须在其内部再创建  
       一个函数  
    """  
    def newDeco(func):    #定义一个新的decorator函数  
        print func, arg  
        return func  
    return newDeco  
@decomaker(deco_args)  
def foo():pass  
foo()
第一个函数decomaker是装饰函数,它的参数是用来加强"加强装饰"的.由于此函数并非被装饰的函数对象,所以在内部必须至少创建一个接受被装饰函数的函数,然后返回这个对象(实际上此时foo=decomaker(arg)(foo)).
备注:修饰器从函数形式上看感觉就是第一个参数应该是被修饰的函数,函数内部不一定非要重新定义一个函数返回,但是必须要返回一个函数.如果第一个参数不是被修饰的函数,函数内部就需要重新定义一个函数.个人感觉函数修饰器带一层参数就需要在内部
定义一次函数.foo=decomaker(arg)(...)(foo),...数量决定了内部定义函数层数.

 

基于类的装饰器
前面的装饰器都是一个函数,其实也可以基于类定义装饰器,看下面的例子:
class Bold(object):
    def __init__(self, func):
        self.func = func
 
    def __call__(self, *args, **kwargs):
        return '<b>' + self.func(*args, **kwargs) + '</b>'
 
@Bold
def hello(name):
    return 'hello %s' % name
 
>>> hello('world')
'<b>hello world</b>'
可以看到,类 Bold 有两个方法:
__init__():它接收一个函数作为参数,也就是被装饰的函数
__call__():让类对象可调用,就像函数调用一样,在调用被装饰函数时被调用
还可以让类装饰器带参数:
class Tag(object):
    def __init__(self, tag):
        self.tag = tag
 
    def __call__(self, func):
        def wrapped(*args, **kwargs):
            return "<{tag}>{res}</{tag}>".format(
                res=func(*args, **kwargs), tag=self.tag
            )
        return wrapped
 
@Tag('b')
def hello(name):
    return 'hello %s' % name
需要注意的是,如果类装饰器有参数,则 __init__ 接收参数,而 __call__ 接收 func.

 

posted on 2016-11-20 18:19  abelian  阅读(112)  评论(0)    收藏  举报