将装饰器的文档字符串放在哪里

Posted

技术标签:

【中文标题】将装饰器的文档字符串放在哪里【英文标题】:Where to put the doc string for a decorator 【发布时间】:2018-11-07 05:27:25 【问题描述】:

我正在尝试记录一个装饰器,但不确定文档字符串应该放在哪里。从技术上讲,它是包含我要记录的参数的内部包装器,但用户将应用外部函数名称作为装饰器。

例如,

def change_case(func):
    """Does the doc string go here
    """
    def _wrapper(s, case=None):
        """Or, does the doc string go here?
        """
        if case == 'Upper':
            s = s.upper()
        elif case == 'Lower':
            s = s.lower()
        return func(s)

    return _wrapper

@change_case
def echo(s):
    return s

echo('Test', case='Upper')

在上面,文档字符串是在 change_case() 还是 _wrapper() 之后。我倾向于前者。

【问题讨论】:

@unutbu 我不认为这种欺骗是正确的。 OP 是在询问 decorator 的文档字符串应该去哪里,而不是如何保存修饰函数的文档字符串。 @Aran-Fey: Different questions may be closed as dupes if understanding the answer to one answers the other. @unutbu 抱歉,我看不到连接。知道你必须在你的内部函数上使用functools.wraps 如何帮助你找出装饰器的文档字符串去哪里?即使您知道@wraps 覆盖了内部函数的文档字符串,将文档字符串放入内部函数仍然是正确的,因为像 IDE 之类的静态代码分析器会拾取它。 【参考方案1】:

将实际装饰器的文档放在***装饰器函数中。当用户尝试使用您的装饰器时,他们希望在这里找到它的文档。例如,从标准库中获取 functools.singledispatch 装饰器:

>>> from functools import singledispatch
>>>
>>> print(singledispatch.__doc__) # the decorator has it's documentation in the actually decorator function
Single-dispatch generic function decorator.

    Transforms a function into a generic function, which can have different
    behaviours depending upon the type of its first argument. The decorated
    function acts as the default implementation, and additional
    implementations can be registered using the register() attribute of the
    generic function.


>>>

但是,您还应该使用functools.wraps 将包含在 decorated 函数中的任何文档传输到包装函数:

>>> from functools import wraps
>>>
>>> def dec(func):
...     @wraps(func)
...     def wrap(*args, **kwargs):
...         return func(*args, **kwargs)
...     return wrap
...
>>> @dec
... def func():
...     """Docstring here"""
...
>>> print(func.__doc__)
Docstring here
>>>

【讨论】:

您可以使用functools.wraps 作为示例而不是functools.singledispatch 使答案更具元性:^) 我知道@Aran-Fey。不过,我不想让 OP 混淆太多;-)

以上是关于将装饰器的文档字符串放在哪里的主要内容,如果未能解决你的问题,请参考以下文章

转发对python装饰器的理解

装饰器的完整实现及原理

Django - 将参数传递给 CBV 装饰器的正确方法?

ES6装饰器的使用

ES6装饰器的使用

JS 装饰器的 ESLint 意外字符“@”