装饰器@


使用多个修饰器的话:

1.  #!/usr/bin/env python  
2.    
3.  def a(fn):  
4.      print 'a'  
5.      def d(st):  
6.          print st+'d'  
7.      return d  
8.    
9.  def b(fn):  
10.     print 'b'  
11.     return fn  
12.  
13. @a  
14. @b  
15. def c(st):  
16.     print st  
17.       
18. c('c')  

我们调用c('c')的时候会先调用b(c),b(c)打印字符"b"然后返回c,然后再调用a(c),a(c)打印字符"a",然后返回方法d,然后再执行d('c'),打印cd。
先调用堆栈里的修饰器里面的函数然后执行显式的函数


后续补充:

双层嵌套:
def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

@log
def now():
    print('2015-3-25')

>>> now()
call now():
2015-3-25

@log def now():
相当于执行了语句:
now = log(now)

三层嵌套:
def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log('execute')
def now():
    print('2015-3-25')

>>> now()
execute now():
2015-3-25

@log('execute')
def now():
相当于 now = log('execute')(now)


Decorator 还可以为类增加额外的成员:
def hello(cls):
     cls.hello = staticmethod(lambda: "HELLO")
     return cls
@hello
class World(object):pass

>>>World.hello( )
'HELLO'

functools.wraps

在使用 Decorator 的过程中,难免会损失一些原本的功能信息

def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log('execute')
def now():
    print('2015-3-25')

>>> now.__name__
'wrapper'                 // 原本应该是now的

-----------------------------------------
加入 @functools.wraps(func) 保留原有的函数签名
def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

你可能感兴趣的:(装饰器@)