亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

帶參數的裝飾器:沒有參數時避免使用括號

帶參數的裝飾器:沒有參數時避免使用括號

慕標琳琳 2021-06-02 18:09:47
下面是我的@logged()裝飾器制造商。它的工作原理大致如下:它接受一個logger實例和一個disabled標志。如果disabled是False,則在裝飾函數之前/之后輸出一些日志。如果disabled是True,則它不輸出任何內容并抑制logger裝飾函數的 。無論是logger和disabled參數有自己的缺省值。但是,當我想使用默認值時,我仍然需要寫空括號,如下所示:@logged()def foo():    pass當我只想要默認參數時,有沒有辦法擺脫這些空括號?這是我想要的一個例子:@loggeddef foo():    pass@logged(disabled=True)def bar():    pass@logged()裝飾器制造商的代碼:import loggingimport logging.configfrom functools import wrapsdef 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_decoratorlogging.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'        }    }
查看完整描述

3 回答

?
夢里花落0921

TA貢獻1772條經驗 獲得超6個贊

它支持兩種開發風格:嵌套(如在 python 裝飾器工廠中)和平面(少一層嵌套)。這是您的示例在平面模式下的實現方式:


from decopatch import function_decorator, DECORATED

from makefun import wraps


@function_decorator

def 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_decorator

def 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


@logged

def bar():

    pass


foo()


bar()

請查看文檔以獲取詳細信息。


查看完整回答
反對 回復 2021-06-08
?
POPMUISE

TA貢獻1765條經驗 獲得超5個贊

或者使用部分(在 Python 食譜中找到的解決方案:9.6)


from functools import wraps, partial


def 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


查看完整回答
反對 回復 2021-06-08
  • 3 回答
  • 0 關注
  • 230 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號