带参数的装饰器

还是直接给出示例,然后再分析:

from functools import wraps
import logging


def logged(level, name=None, message=None):
    '''
    Add logging to a function. level is the logging level, name is the logger name, and message is the log message. If name and message aren't specified, they default to the function's module and name.
    '''
    def decorate(func):
        logname = name if name else func.__module__
        log = logging.getLogger(logname)
        logmsg = message if message else func.__name__

        @wraps(func)
        def wrapper(*args, **kwargs):
            log.log(level, logmsg)
            return func(*args, **kwargs)
        return wrapper
    return decorate


# Example use
@logged(logging.DEBUG)
def add(x, y):
    return x + y


@logged(logging.CRITICAL, 'example')
def spam():
    print('Spam!')

乍一看,该实现看起来很棘手,但想法相对简单。 最外层的函数logging()接受所需的参数,并使它们可用于装饰器的内部函数。 内部函数decorate()接受一个函数,并像往常一样在其周围放置包装。 关键部分是允许包装器使用传递给Logged()的参数。

装饰器接收参数可以按照以下示例转化:

@decorator(x, y, z)
def func(a, b):
    pass

相当于:

def func(a, b):
    pass

func = decorator(x, y, z)(func)
posted @ 2020-02-03 16:05  Jeffrey_Yang  阅读(177)  评论(0编辑  收藏  举报