您可以使用装饰器向内部函数添加额外的参数吗?
Can you use a decorator to add an additional parameter to the inner function?
是否有使用装饰器向装饰的(内部)函数添加另一个参数的(好)方法。我想我已经找到了一种可以完成其中一部分的方法,但看起来很老套并且至少有一个问题。
我的场景(我可能会以更好的方式解决,但只是想知道这里)是针对我 运行 的每日数据脚本,我希望某些函数具有 [=40= 的参数] 这会为每个阶段做同样的事情。例如,
def func(arg1,arg2,phase):
# do some stuff specific to the function
if phase == 1:
pass
elif phase == 2:
# do something else, the same something in multiple different functions
else:
raise ValueError('phase needs to be 1 or 2')
我发现自己在 'do some stuff' 之后用 4 个不同的函数写了完全相同的东西。所以我想也许我可以使用装饰器来基本上添加从 if phase == 1
到末尾的所有内容,并且只在每个 func 中包含它独有的 do stuff
。
在一些测试中,我找到了一种方法来完成这个,但我不确定这是否是最好的方法,而且文档字符串也变得一团糟......这是我目前所拥有的:
import functools
def add_phase(func):
add_to_doc = """\nhere is the add_phase docstring"""
func.__doc__ += add_to_doc
@functools.wraps(func)
def wrapper(param, phase):
"""here is the wrapper docstring"""
if phase == 1:
print("got to this line")
elif phase == 2:
return func(param)
else:
raise ValueError
return wrapper
@add_phase
def func(param):
"here is the reg1 docstring"
st = f"statement {param}"
print(st)
func("param", phase=2)
有了这些,我就可以用两个参数调用 func
并且它起作用了。但是,当我在其上调用 help
时,它表明它只需要 param
而不是 phase
.
我还想将装饰器正在说明 phase
做什么的任何函数的信息添加到文档字符串中。在我们到达包装器之前,我能够通过在装饰器 add_phase
中放置 add_to_doc...
两行来实现这一点。这导致 help(func)
给出文档字符串及其原始内容和添加内容。但它仍然只显示一个参数。此外,当我将鼠标悬停在 VSCode 中的 func
上时,那里的帮助文本只提供了 func 文档字符串,而不是添加了装饰器文档字符串信息。
那么,是否有一些我缺少的已经开发的方法可以做到这一点?这种方法可能会失败吗?有没有办法更新文档字符串中参数中显示的内容?
最后,是的,我可以通过在函数外部测试 phase
并将它们全部放在一个 if 块中来更轻松地完成此特定任务,但这会很无聊。
只是不要 functools.wrap 函数...
def add_phase(func):
def wrapper(param, phase):
if phase == 1:
print("got to this line")
elif phase == 2:
return func(param)
else:
raise ValueError
wrapper.__doc__ = f"Wraps: {func.__name__} and injects an arg\n{func.__doc__}"
return wrapper
那你就可以看到了
>>> help(func)
Help on function wrapper in module __main__:
wrapper(param, phase)
Wraps: func and injects an arg
here is the reg1 docstring
但实际上这似乎会很痛苦,而且是个坏主意...
是否有使用装饰器向装饰的(内部)函数添加另一个参数的(好)方法。我想我已经找到了一种可以完成其中一部分的方法,但看起来很老套并且至少有一个问题。
我的场景(我可能会以更好的方式解决,但只是想知道这里)是针对我 运行 的每日数据脚本,我希望某些函数具有 [=40= 的参数] 这会为每个阶段做同样的事情。例如,
def func(arg1,arg2,phase):
# do some stuff specific to the function
if phase == 1:
pass
elif phase == 2:
# do something else, the same something in multiple different functions
else:
raise ValueError('phase needs to be 1 or 2')
我发现自己在 'do some stuff' 之后用 4 个不同的函数写了完全相同的东西。所以我想也许我可以使用装饰器来基本上添加从 if phase == 1
到末尾的所有内容,并且只在每个 func 中包含它独有的 do stuff
。
在一些测试中,我找到了一种方法来完成这个,但我不确定这是否是最好的方法,而且文档字符串也变得一团糟......这是我目前所拥有的:
import functools
def add_phase(func):
add_to_doc = """\nhere is the add_phase docstring"""
func.__doc__ += add_to_doc
@functools.wraps(func)
def wrapper(param, phase):
"""here is the wrapper docstring"""
if phase == 1:
print("got to this line")
elif phase == 2:
return func(param)
else:
raise ValueError
return wrapper
@add_phase
def func(param):
"here is the reg1 docstring"
st = f"statement {param}"
print(st)
func("param", phase=2)
有了这些,我就可以用两个参数调用 func
并且它起作用了。但是,当我在其上调用 help
时,它表明它只需要 param
而不是 phase
.
我还想将装饰器正在说明 phase
做什么的任何函数的信息添加到文档字符串中。在我们到达包装器之前,我能够通过在装饰器 add_phase
中放置 add_to_doc...
两行来实现这一点。这导致 help(func)
给出文档字符串及其原始内容和添加内容。但它仍然只显示一个参数。此外,当我将鼠标悬停在 VSCode 中的 func
上时,那里的帮助文本只提供了 func 文档字符串,而不是添加了装饰器文档字符串信息。
那么,是否有一些我缺少的已经开发的方法可以做到这一点?这种方法可能会失败吗?有没有办法更新文档字符串中参数中显示的内容?
最后,是的,我可以通过在函数外部测试 phase
并将它们全部放在一个 if 块中来更轻松地完成此特定任务,但这会很无聊。
只是不要 functools.wrap 函数...
def add_phase(func):
def wrapper(param, phase):
if phase == 1:
print("got to this line")
elif phase == 2:
return func(param)
else:
raise ValueError
wrapper.__doc__ = f"Wraps: {func.__name__} and injects an arg\n{func.__doc__}"
return wrapper
那你就可以看到了
>>> help(func)
Help on function wrapper in module __main__:
wrapper(param, phase)
Wraps: func and injects an arg
here is the reg1 docstring
但实际上这似乎会很痛苦,而且是个坏主意...