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.