【发布时间】:2021-04-11 20:54:34
【问题描述】:
通过包装器向函数添加参数是 python 反模式吗?我想添加一个包装器,将许多函数的输出保存到一个位置,所以包装器似乎很有意义。但是,Pycharm 无法自动完成修饰函数的参数 (https://intellij-support.jetbrains.com/hc/en-us/community/posts/360002754060-Autocomplete-with-arguments-for-decorated-functions)。
一些与使用包装器更改函数签名相关的讨论似乎表明这是一种不好的做法 (https://youtrack.jetbrains.com/issue/PY-33688#focus=Comments-27-3268273.0-0)。
一些装饰器可能会更改函数的签名,以便正确处理此类情况 PyCharm 必须读取由于性能原因而无法完成的装饰器主体。
因此,执行以下操作会是一种反模式:
from functools import wraps
from typing import Callable
my_dict = {"very": {"deeply": {"nested": {"filepath": "hidden_filepath"}}}}
def decorator(function: Callable):
@wraps(function)
def wrapper(extra_arg: str, function_arg: str) -> str:
file_path: str = my_dict["very"]["deeply"]["nested"][extra_arg]
print(f"saving to: {file_path}")
result: str = function(function_arg)
print(f"result: {result}")
return result
wrapper.__doc__ += "/n:param extra_arg: an extra argument"
return wrapper
@decorator
def my_function(an_arg: str) -> str:
"""
my docstring
:param an_arg:
:return:
"""
print(f"my_function arg: {an_arg}")
return an_arg * 2
my_function("filepath", "cool_str")
我也不喜欢在函数中附加文档字符串,但在这里找到了解决方案:Signature-changing decorator: properly documenting additional argument。只更改装饰函数的文档字符串是否更有意义?
编辑: 我能想到的唯一其他合理的解决方案是创建一个将另一个函数作为参数的函数,这是包装器应该解决的问题,例如。
def decorator(extra_arg:str, function: Callable, **kwargs)-> str:
file_path: str = my_dict["very"]["deeply"]["nested"][extra_arg]
print(f"saving to: {file_path}")
result: str = function(**kwargs)
print(f"result: {result}")
return result
def my_function(an_arg: str) -> str:
"""
my docstring
:param an_arg:
:return:
"""
print(f"my_function arg: {an_arg}")
return an_arg * 2
decorator("filepath", my_function, an_arg="cool_str")
【问题讨论】:
-
不确定“反模式”部分,但如果我看到这样的代码,我可能会重构它。幕后花絮太多了。
-
@rdas,看我的编辑,那是你要重构的吗?它似乎不是一个优越的解决方案,你没有从你的 IDE 中得到任何参数提示,重构不是 IDE 辅助的,等等。
-
取决于您的实际程序,但我不希望看到每个函数调用都通过另一个函数调用。可能有更简单的方法来做你想做的事情,但这需要更多关于细节的细节。
-
@rdas,谢谢,同意。我基本上是在尝试做上述事情。将任何随机函数的结果保存到其路径存储在深度嵌套字典中的文件中。我还想在函数调用周围有一些打印语句(我目前绑定到 print() 作为我的记录器)
标签: python decorator python-decorators anti-patterns functools