如何将 *args
和 **kwargs
替换为装饰函数文档中的真实签名?
假设我有以下装饰器和装饰功能:
import functools
def mywrapper(func):
@functools.wraps(func)
def new_func(*args, **kwargs):
print('Wrapping Ho!')
return func(*args, **kwargs)
return new_func
@mywrapper
def myfunc(foo=42, bar=43):
"""Obscure Addition
:param foo: bar!
:param bar: bla bla
:return: foo + bar
"""
return foo + bar
因此,调用 print(myfunc(3, 4))
给我们:
Wrapping Ho!
7
到现在为止还挺好 . 我还希望我的库包含 myfunc
与Sphinx正确记录 . 但是,如果我通过以下方式将我的函数包含在我的sphinx html页面中:
.. automodule:: mymodule
:members: myfunc
它实际上会显示为:
myfunc(* args,** kwargs)
模糊的加法
-
Parameters:
-
foo :吧!
-
bar :bla bla
-
Returns: foo吧
如何摆脱 Headers 中的泛型 myfunc(*args, **kwargs)
?这应该被 myfunc(foo=42, bar=43) 取代 . 如何更改sphinx或我的装饰器 mywrapper
,以便在文档中保留默认关键字参数?
EDIT :
正如之前所指出的那样,这个问题已被提出,但答案并没有那么有用 .
但是,我有一个想法,并想知道这是否可行 . Sphinx是否设置了一些环境变量,告诉我的模块它实际上是由Sphinx导入的?如果是这样,我可以简单地修补我自己的包装 . 如果我的模块是由Sphinx导入的,我的包装器将返回原始函数而不是包装它们 . 因此,签名得以保留 .
2 回答
我为
functools.wraps
想出了一个猴子补丁 . 因此,我只是将其添加到项目文档的sphinxsource
文件夹中的conf.py
脚本中:因此,当通过
make html
构建html页面时,functools.wraps
被替换为这个装饰器no_op_wraps
,除了简单地返回原始函数之外什么都不做 .你通常不能 . 这是因为在包装函数中用作参数的变量名称甚至不存在于包装函数中 - 因此Sphinx不知道它们 .
这是Python中一个已知的复杂问题 - 最近的版本 - 不仅包括Python 3,还包括Python 2.7在类装饰上包含
__wrapped__
属性,从functools.wraps
开始正确使用 - 这样,在检查装饰函数时,一个是通过查看__wrapped__
能够了解实际的扭曲功能 . 不幸的是,Sphinxs忽略了__wrapped__
,而是在包装函数上显示信息 .因此,要做的一件事当然是将此报告为Sphinx项目本身的一个错误 - 它应该考虑
__wrapped__
.同时解决这个问题的方法是更改包装函数以实际包含有关包装的更多信息 - 比如它的签名 - 这样你就可以为你的项目编写另一个函数来代替"functools.wraps"来调用它:pre-pend其文档字符串的函数签名(如果有) . 不幸的是,在3.3以上的Python中检索函数签名是棘手的 - (对于3.3和更新版本,检查https://docs.python.org/3/library/inspect.html#inspect-signature-object) - 但无论如何,对于一个天真的形式,你可以编写另一个版本的"wraps":
并使用它而不是“functools.wraps” . 它至少会添加一个带有参数名称的行(但不是defalt值)作为文档中的第一行 .
---嗯......可能只是在完成这项工作之前修补Sphinx以使用
__wrapped__
会更容易 .