理解嵌套装饰器缺少必需的位置参数错误
Understanding nested decorators missing required positional argument error
我写了两个装饰器,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
本身工作正常。怎么回事?
我认为问题出在这一行:
def wrapper_func(verbboo=True, *args, **kwargs):
函数定义必须在任何关键字参数之前包含所有位置参数。可能是关键字参数 verboo 干扰了位置参数 boo 的通过。
当我把verbboo参数放在末尾时,它仍然没有运行,但是当我把它放在*args和**kwargs之间时,它运行。
我写了两个装饰器,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
本身工作正常。怎么回事?
我认为问题出在这一行:
def wrapper_func(verbboo=True, *args, **kwargs):
函数定义必须在任何关键字参数之前包含所有位置参数。可能是关键字参数 verboo 干扰了位置参数 boo 的通过。
当我把verbboo参数放在末尾时,它仍然没有运行,但是当我把它放在*args和**kwargs之间时,它运行。