带参数的装饰器:没有参数时避免使用括号

下面是我的@logged()装饰器制造商。它的工作原理大致如下:

  1. 它接受一个logger实例和一个disabled标志。

  2. 如果disabledFalse,则在装饰函数之前/之后输出一些日志。

  3. 如果disabledTrue,则它不输出任何内容并抑制logger装饰函数的 。

无论是loggerdisabled参数有自己的缺省值。但是,当我想使用默认值时,我仍然需要写空括号,如下所示:

@logged()

def foo():

    pass

当我只想要默认参数时,有没有办法摆脱这些空括号?这是我想要的一个例子:


@logged

def foo():

    pass


@logged(disabled=True)

def bar():

    pass

@logged()装饰器制造商的代码:


import logging

import logging.config


from functools import wraps


def logged(logger=logging.getLogger('default'), disabled=False):

    '''

    Create a configured decorator that controls logging output of a function


    :param logger: the logger to send output to

    :param disabled: True if the logger should be disabled, False otherwise

    '''


    def logged_decorator(foo):

        '''

        Decorate a function and surround its call with enter/leave logs


        Produce logging output of the form:

        > enter foo

          ...

        > leave foo (returned value)

        '''


        @wraps(foo)

        def wrapper(*args, **kwargs):


            was_disabled = logger.disabled


            # If the logger was not already disabled by something else, see if

            # it should be disabled by us. Important effect: if foo uses the

            # same logger, then any inner logging will be disabled as well.

            if not was_disabled:

                logger.disabled = disabled


            logger.debug(f'enter {foo.__qualname__}')


            result = foo(*args, **kwargs)


            logger.debug(f'leave {foo.__qualname__} ({result})')


            # Restore previous logger state:

            logger.disabled = was_disabled


            return result


        return wrapper


    return logged_decorator


logging.config.dictConfig({

    'version': 1,

    'formatters': {

        'verbose': {

            'format': '%(asctime)22s %(levelname)7s %(module)10s %(process)6d %(thread)15d %(message)s'

        }

        , 'simple': {

            'format': '%(levelname)s %(message)s'

        }

    }


慕标琳琳
浏览 203回答 3
3回答

梦里花落0921

它支持两种开发风格:嵌套(如在 python 装饰器工厂中)和平面(少一层嵌套)。这是您的示例在平面模式下的实现方式:from decopatch import function_decorator, DECORATEDfrom makefun import wraps@function_decoratordef logged(disabled=False, logger=logging.getLogger('default'), func=DECORATED):    # (1) create a signature-preserving wrapper    @wraps(func)    def _func_wrapper(*f_args, **f_kwargs):        # stuff        result = func(*f_args, **f_kwargs)        # stuff        return result    # (2) return it    return _func_wrapper请注意,我使用makefun.wraps而不是functools.wraps此处,以便完全保留签名(如果参数无效,则根本不会调用包装器)。decopatch支持另一种开发风格,我称之为double-flat,专门用于创建这样的签名保留函数包装器。您的示例将像这样实现:from decopatch import function_decorator, WRAPPED, F_ARGS, F_KWARGS@function_decoratordef logged(disabled=False, logger=logging.getLogger('default'),            func=WRAPPED, f_args=F_ARGS, f_kwargs=F_KWARGS):    # this is directly the signature-preserving wrapper    # stuff    result = func(*f_args, **f_kwargs)    # stuff    return result您可以检查两种样式是否按预期工作:@logged(disabled=True)def foo():    pass@loggeddef bar():    passfoo()bar()请查看文档以获取详细信息。

POPMUISE

或者使用部分(在 Python 食谱中找到的解决方案:9.6)from functools import wraps, partialdef foo(func=None, *, a=None, b=None):    if func is None:        return partial(foo, a=a, b=b)    @wraps(func)    def wrapper(*args, **kwargs):        return func(*args, **kwargs)    return wrapper
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python