模仿Python文档字符串

wim*_*wim 4 python docstring

为什么动态格式化文档字符串不起作用?在功能定义时有没有可接受的解决方法?

>>> DEFAULT_BAR = "moe's tavern"
>>> def foo(bar=DEFAULT_BAR):
...     """
...     hello this is the docstring
...     
...     Args:
...       bar (str)    the bar argument (default: {})
...     """.format(DEFAULT_BAR)
... 
>>> foo.__doc__
>>> foo.__doc__ is None
True
Run Code Online (Sandbox Code Playgroud)

我尝试使用old-skool样式的%s格式,但也无法正常工作.

Mar*_*ers 8

您的字符串需要调用函数,但在创建函数时不会执行函数体.

没有执行正确的文档字符串,它只是从解析的源代码中获取并附加到函数对象,没有为此执行任何代码.Python将docstring存储为代码对象中的第一个常量值:

>>> def f():
...     """docstring"""
...     pass
...
>>> f.__code__.co_consts
('docstring', None)
Run Code Online (Sandbox Code Playgroud)

在构造新函数时将代码对象传递给函数类型(请参阅PyFunction_New()函数).

请参阅函数定义参考文档:

函数定义不执行函数体; 只有在调用函数时才会执行此操作.[3]

[...]

[3]作为函数体中第一个语句出现的字符串文字被转换为函数的__doc__属性,因此转换为函数的docstring.

您的定义是有效的; 在函数体的顶部没有独立的字符串文字.您的字符串文字是函数本身的一部分,并且仅在调用函数时执行(并且因为您不存储该结果而丢弃结果).

请注意,__doc__函数对象上的属性是可写的; 您可以创建函数始终应用变量:

>>> DEFAULT_BAR = "moe's tavern"
>>> def foo(bar=DEFAULT_BAR):
...     """
...     hello this is the docstring
...
...     Args:
...       bar (str)    the bar argument (default: {})
...     """
...
>>> foo.__doc__ = foo.__doc__.format(DEFAULT_BAR)
>>> print(foo.__doc__)

    hello this is the docstring

    Args:
      bar (str)    the bar argument (default: moe's tavern)
Run Code Online (Sandbox Code Playgroud)

你可以做,在的帮助下一个装饰functionobject.__globals__inspect.getargspec()可能,但随后就在模板中使用名为插槽,您可以将一切视为一个字典,并有文档字符串选择什么插值:

from inspect import getargspec

def docstringtemplate(f):
    """Treat the docstring as a template, with access to globals and defaults"""
    spec = getargspec(f)
    defaults = {} if not spec.defaults else dict(zip(spec.args[-len(spec.defaults):], spec.defaults))
    f.__doc__ = f.__doc__ and f.__doc__.format(**dict(f.__globals__, **defaults))
    return f
Run Code Online (Sandbox Code Playgroud)

演示:

>>> @docstringtemplate
... def foo(bar=DEFAULT_BAR):
...     """
...     hello this is the docstring
...
...     Args:
...       bar (str)    the bar argument (default: {bar!r}, or {DEFAULT_BAR!r})
...
...     """
...
>>> print(foo.__doc__)

    hello this is the docstring

    Args:
      bar (str)    the bar argument (default: "moe's tavern", or "moe's tavern")
Run Code Online (Sandbox Code Playgroud)

函数关键字参数会覆盖全局变量,就像它们在函数中一样.