[我写了两个装饰器,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):
函数定义必须在所有关键字参数之前都包含所有位置参数。关键字参数verbboo可能会干扰位置参数boo的传递。
[当我将verbboo参数放在最后时,它仍然没有运行,但是当我将它放在* args和** kwargs之间时,它确实运行了。