了解嵌套装饰器缺少必需的位置参数错误

问题描述 投票:0回答:1

[我写了两个装饰器,verbose控制是否定义的函数打印其输出,announcer将在调用该函数时宣布。

import os
import sys

def verbose(func):
    '''Sets verbose mode on function'''
    @functools.wraps(func)
    def wrapper_func(verbboo=True, *args, **kwargs):
        # disabling print
        if not verbboo:
            sys.stdout = open(os.devnull, 'w')
        # running func
        ret = func(*args, **kwargs)
        # enabling print again
        if not verbboo:
            sys.stdout = sys.__stdout__
        return ret
    return wrapper_func

def announcer(func, endboo=True):
    '''anounces when function is called and when it finishes; if specified'''
    @functools.wraps(func)
    def wrapper_func(*args, **kwargs):
        print('run {}.{}@{:%Y%m%d%H%M}'.format(
            func.__module__, func.__name__,
            dt.datetime.now())
        )
        ret = func(*args, **kwargs)
        if endboo:
            print('end {}.{}@{:%Y%m%d%H%M}'.format(
                func.__module__, func.__name__,
                dt.datetime.now())
            )
        return ret
    return wrapper_func

然后将以下函数与装饰器嵌套

@verbose
@announcer
def f(boo, opboo=True):
    if boo:
        print('This is True')
    if opboo:
        print('This is also True')

    return f

# testing
f(True)

但是我收到以下错误

run __main__.f@202006021152
Traceback (most recent call last):
  File "/home/user/anaconda3/envs/mpl/lib/python3.8/runpy.py", line 193, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/home/user/anaconda3/envs/mpl/lib/python3.8/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/home/user/project/test.py", line 17, in <module>
    f(True)
  File "/home/user/project/decorators.py", line 18, in wrapper_func
    ret = func(*args, **kwargs)
  File "/home/user/project/decorators.py", line 47, in wrapper_func
    ret = func(*args, **kwargs)
TypeError: f() missing 1 required positional argument: 'boo'

仅当我将verbose嵌套在announcer顶部时,才会发生错误。 announcer本身可以正常工作。这是怎么回事?

python python-3.x python-decorators
1个回答
0
投票

我认为问题出在这一行:

def wrapper_func(verbboo=True, *args, **kwargs):

函数定义必须在所有关键字参数之前都包含所有位置参数。关键字参数verbboo可能会干扰位置参数boo的传递。

[当我将verbboo参数放在最后时,它仍然没有运行,但是当我将它放在* args和** kwargs之间时,它确实运行了。

© www.soinside.com 2019 - 2024. All rights reserved.