普通装饰器
1. 不带参数的普通装饰器
1 from functools import wraps 2 3 def use_logging(func): 4 @wraps(func) # 使得装饰器函数和原函数有一样的原信息(docstring、__name__等),但为方便,下面的例子没有使用。 5 def wrapper(*args, **kw): 6 print args 7 print kw 8 return func(*args, **kw) 9 return wrapper 10 11 @use_logging 12 def foo(x, n=1): 13 print x, n 14 print 'I am foo' 15 16 foo(3) 17 foo(1, n=2)
输出如下:
# foo(3) (3,) {} # 因为foo(x, n=1)是在user_logging之后调用的,foo(3)时并未传其他参数,所以这里输出为空。 3 1 I am foo # foo(1, n=2) (1,) {'n': 2} 1 2 I am foo
2. 带参数的普通装饰器
1 def use_logging(level): 2 def decorator(func): 3 def wrapper(*args, **kw): 4 if level == 'warning': 5 print '%s is running' % func.__name__ 6 return func(*args, **kw) 7 return wrapper 8 return decorator 9 10 @use_logging(level='warning') 11 def foo(name='FOO'): 12 print 'I am %s' % name 13 14 @use_logging(level='info') 15 def bar(name='BAR'): 16 print 'I am %s' % name 17 18 foo() 19 bar()
输出:
# foo() foo is running I am FOO # bar() I am BAR
装饰器类
类装饰器具有灵活度大、高内聚、封装性等优点。当使用 @ 形式将装饰器附加到函数上时,就会调用 __call__() 方法。
1. 不带参数的装饰器类
1 class FOO(object): 2 def __init__(self, func): 3 self._func = func 4 5 def __call__(self, *args, **kw): 6 print args, kw 7 kw['x'] = 34 8 return self._func(*args, **kw) 9 10 @FOO 11 def bar(a, x=1): 12 print a, x 13 print 'I am bar' 14 15 bar(3,x=7)
输出:
(3,) {'x': 7} 3 34 I am bar
2. 带参数的装饰器类
1 class FOO(object): 2 def __init__(self, level='debug'): 3 self._level = level 4 5 def __call__(self, func): 6 def _call(*args, **kw): 7 print args, kw 8 if self._level == 'error': 9 kw['x'] = 34 10 return func(*args, **kw) 11 return _call 12 13 @FOO('error') # FOO() 14 def foo(a, x=1): 15 print a, x 16 print 'I am foo' 17 18 @FOO('info') 19 def bar(a, x=1): 20 print a, x 21 print 'I am bar' 22 23 foo(2) 24 bar(3,x=7)
输出:
# foo(2) (2,) {} 2 34 I am foo # bar(d, x=7) (3,) {'x': 7} 3 7 I am bar
另外一种带参数的装饰器类的写法如下:
1 class FOO(object): 2 def __init__(self, level): 3 self._level = level 4 5 def __call__(self, func): 6 self._func = func 7 return self._call 8 9 def _call(self, *args, **kw): 10 print args, kw 11 if self._level == 'error': 12 kw['x'] = 34 13 return self._func(*args, **kw) 14 15 @FOO('error') 16 def foo(a, x=1): 17 print a, x 18 print 'I am foo' 19 20 @FOO(level='info') 21 def bar(a, x=1): 22 print a, x 23 print 'I am bar' 24 25 foo(2) 26 bar(3,x=7)
输出的结果如上面的一致,注意加粗的地方。