Python 之 装饰器的写法

普通装饰器

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)

输出的结果如上面的一致,注意加粗的地方。

原文地址:https://www.cnblogs.com/liuq/p/6093324.html