【问题标题】:How to put a variable into Python docstring如何将变量放入 Python 文档字符串
【发布时间】:2012-05-05 16:00:57
【问题描述】:

所以我正在尝试创建一个类似这样的“动态”文档字符串:

ANIMAL_TYPES = ["mammals", "reptiles", "other"]

def func(animalType):
""" This is a sample function.

    @param animalType: "It takes one of these animal types %s" % ANIMAL_TYPES
"""

基本上让@param animalType 的文档字符串显示ANIMAL_TYPES 的任何内容;这样当更新此变量时,文档字符串将自动更新。

不幸的是,它似乎不起作用。有谁知道是否有办法实现这一目标?

【问题讨论】:

    标签: python docstring


    【解决方案1】:

    三引号字符串是一个大字符串。在它们内部没有进行任何评估。 % 部分是字符串的全部部分。你需要让它在实际的字符串上运行。

    def func(animalType):
        """
        This is a sample function.
    
        @param animalType: "It takes one of these animal types %(ANIMAL_TYPES)s"
        """ % {'ANIMAL_TYPES': ANIMAL_TYPES}
    

    不过,我不确定这是否能正常工作;文档字符串有点神奇。 这将起作用; docstring 在编译时被评估(作为函数中的第一个语句,因为它是一个字符串文字——一旦它得到 % 它就不仅仅是一个字符串文字),字符串格式化发生在运行时,所以 @987654324 @ 将为空:

    >>> def a(): 'docstring works'
    ... 
    >>> a.__doc__
    'docstring works'
    >>> def b(): "formatted docstring doesn't work %s" % ':-('
    ... 
    >>> b.__doc__
    >>> 
    

    如果您想以这种方式工作,则需要在定义函数后执行func.__doc__ %= {'ANIMAL_TYPES': ANIMAL_TYPES}。请注意,如果您没有检查 __doc__ 是否已定义,那么这将在 python -OO 上中断,因为 -OO 会删除文档字符串。

    >>> def c(): "formatted docstring works %s"
    ... 
    >>> c.__doc__
    "formatted docstring works %s"
    >>> c.__doc__ %= 'after'
    >>> c.__doc__
    "formatted docstring works after"
    

    无论如何,这不是标准技术;标准技术是引用适当的常量:“采用 ANIMAL_TYPES 中的一种动物类型”,或类似的。

    【讨论】:

    • 谢谢,克里斯。我可以问为什么__doc__ 在你划掉的代码中会是空的吗?谢谢!
    • 它为空的原因是因为 表达式 'foo %s' % 'bar' 不是字符串文字,它是一个可以计算为字符串的表达式。编译器期望一个真正的字符串文字,作为块内的第一件事,作为一个文档字符串。
    • 我最终采纳了最后一个代码 sn-p 中的建议。我试图做“在 ANIMAL_TYPES 中采用一种动物类型”,但效果不佳,因为我正在为一个将由 SPHINX 生成的 API 编写文档字符串,并且它不会打印出常量的内容在文档中,无论我尝试了什么...... :( 所以现在就像(请参阅原始帖子。代码在这里的格式不太好......)
    【解决方案2】:

    您可以简单地在您的文档字符串中使用cross-references 来引用该变量。

    所以:

    :param animalType: It takes one of these :data:`animal types<ANIMAL_TYPES>`
    

    第二个:

    :param choice: can be one of :attr:`MY_CONST`
    

    【讨论】:

    【解决方案3】:

    你也可以使用.__doc__定义一个文档字符串

    例如:

    >>> def f():
          pass
    >>> x = 1
    >>> y = "docstring"
    
    >>> f.__doc__ = "%s string %s" % (x, y)
    >>> print(f.__doc__)
    1 string docstring
    

    【讨论】:

      【解决方案4】:

      一种方法是使用装饰器。我不确定我对此有何感想;我实际上搜索了有关此方法的评论并找到了this answer,它正确地指出它可能掩盖了设计问题。但乍一看,您的用例似乎听起来不错。

      无论如何,这里有一个相当优雅的方式来实现您正在寻找的结果:

      >>> def docstring_parameter(*sub):
      ...     def dec(obj):
      ...         obj.__doc__ = obj.__doc__.format(*sub)
      ...         return obj
      ...     return dec
      ... 
      >>> @docstring_parameter('Ocean')
      ... def foo():
      ...     '''My Docstring Lies Over The {0}'''
      ...     pass
      ... 
      >>> @docstring_parameter('Sea')
      ... def bar():
      ...     '''My Docstring Lies Over The {0}'''
      ...     pass
      ... 
      >>> @docstring_parameter('Docstring', 'Me')
      ... def baz():
      ...     '''Oh Bring Back My {0} To {1}'''
      ...     pass
      ... 
      >>> foo.__doc__
      'My Docstring Lies Over The Ocean'
      >>> bar.__doc__
      'My Docstring Lies Over The Sea'
      >>> foo.__doc__
      'My Docstring Lies Over The Ocean'
      >>> baz.__doc__
      'Oh Bring Back My Docstring To Me'
      

      【讨论】:

      • 如果可以的话,对这个答案稍作修改:def docstring_parameter(*args, **kwargs):,然后是obj.__doc__ = obj.__doc__.format(*args, **kwargs)。现在,您可以这样做:@docstring_parameter('Docstring', 'Me', yeah='yeah')'''Oh Bring Back My {} To {}. {yeah}!'''。最后,print(baz.__doc__) 打印出'Oh Bring Back My Docstring To Me. yeah!'。谢谢!
      • 很好的补充@nik_m。我想进一步改进您的解决方案,注意检查obj.__doc__ is not None 将解决函数中未设置文档字符串的问题!
      猜你喜欢
      • 2017-10-28
      • 2020-05-31
      • 2017-09-08
      • 2019-08-14
      • 1970-01-01
      • 2011-12-09
      • 2020-09-03
      • 1970-01-01
      相关资源
      最近更新 更多