基础用法:廖雪峰python教程

# log为装饰器decorator
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()  相当于执行 now = log(now),可以发现now的__name__属性变为wrapper,使用functools工具确保被装饰函数的name属性不变

import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

若装饰器带参数,需要编写一个返回decorator的高阶函数

import functools

def log(text):
    def decorator(func):
        @functools.wraps(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

等价于now = log('execute')(now)
'''

 


拓展到类装饰器(如下解释):参考

  • 装饰器无参数
class tracer: 
    def __init__(self,func): 
        self.calls = 0 
        self.func = func
        print("dd", func.__name__)
    def __call__(self,*args): 
        self.calls += 1 
        print('call %s to %s' %(self.calls, self.func.__name__)) 
        self.func(*args) 

@tracer
def spam(a, b, c): 
    print(a + b + c) 
# 写完运行结果有dd spam

@tracer
def spam2(a, b, c): 
    print(a - b - c) 
# 写完运行结果有dd spam2

'''相当于实例化了'''

  • 装饰器有参数
class tracer:  
    def __init__(self, *args):  
        self.calls = 0
        self.args = args

    def __call__(self, func):
        self.func = func
        def realfunc(*args):
              self.calls += 1
              print('call %s to %s' %(self.calls, self.func.__name__))
              self.func(*args)
        return realfunc

@tracer("xxxx")
def spam(a, b, c):  
    print(a + b + c)  

# 相当于是把待装饰的函数当参数传给了call函数

相当于实例化类之后,再装饰

 

装饰器应用

 

posted on 2018-12-10 10:56  笨拙的忍者  阅读(159)  评论(0编辑  收藏  举报