单个模块/功能等超过1个文档字符串?

时间:2010-02-13 19:13:55

标签: python docstring

我正在使用python 3.1。

是否可以为单个模块或函数创建多个文档字符串? 我正在创建一个程序,我打算有多个docstrings,每个都有一个类别。我打算给其他人这个程序,以便他们可以使用它,并为程序员和非程序员提供方便,我正在为程序本身的文档提供文档字符串。

更具体地说,我在程序/模块中有一个菜单作为接口,其中一个选项将允许访问模块docstring以获取程序文档。因此,如果可能的话,我想制作多个文档字符串来对不同类型的文档进行分类。因此,如果用户希望查看文档的某些部分,那么对用户来说会更容易。

例如。第一个docstring包含有关如何使用该程序的说明。第二个docstring包含有关程序的一部分如何工作的信息。第三个docstring包含有关另一部分如何工作的信息。等

这可能吗?如果是这样,你如何引用它们?

更新:添加评论。

我最初的想法实际上是在以下意义上有多个文档字符串:

def foo():
    """docstring1: blah blah blah"""
    """docstring2: blah blah blah"""
    pass # Insert code here

然后会有一些代码可以让我引用这些文档字符串。 那么,我猜这是不可能的呢?

5 个答案:

答案 0 :(得分:4)

我不建议尝试使用docstrings做一些复杂的事情。最好保持文档字符串简单,如果你想提供一堆不同的文档选项,还可以做其他事情。

如果你真的想做你所描述的,我建议你用标签分隔文档字符串中的部分。像这样:

def foo(bar, baz):
    """Function foo()

* Summary:
    Function foo() handles all your foo-ish needs.  You pass in a bar and a baz and it foos them.

* Developers:
    When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests.

* Testers:
    When you test foo, be sure to try negative values for baz.
"""
    pass # code would go here

然后你可以很容易地将你的字符串拆分成块,当用户选择一个菜单项时,只显示相应的块。

s = foo.__doc__  # s now refers to the docstring

lst = s.split("\n* ")
section = [section for section in lst if section.startswith("Developers")][0]
print(section) # prints the "Developers" section

这样,当您在交互式Python shell中工作时,您可以说“help(foo)”,您将看到所有文档字符串。并且,您并没有改变Python基本部分的基本行为,这会让其他人试图研究您的代码。

您还可以做一些更简单的事情:只需为不同目的制作一个大型的全球文档字典,并从每个新事物的源代码中更新它。

doc_developers = {} doc_testers = {}

def foo(bar, baz):
    """Function foo()

Function foo() handles all your foo-ish needs.  You pass in a bar and a baz and it foos them."
    pass # code goes here

doc_developers["foo"] = "When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests."

doc_testers["foo"] = "When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests."

我最不喜欢的是,如果你改变函数foo的名称,你需要在多个地方更改它:一次在实际的def中,一次在每个字典更新行中。但你可以通过写一个函数来解决这个问题:

def doc_dict = {} # this will be a dict of dicts
doc_dict["developers"] = {}
doc_dict["testers"] = {}

def doc_update(fn, d):
    name = fn.__name__
    for key, value in d.items():
        doc_dict[key][name] = value

def foo(bar, baz):
    """Function foo()

Function foo() handles all your foo-ish needs.  You pass in a bar and a baz and it foos them."
    pass # code goes here

d = { "developers": "When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests.",
"testers": " When you test foo, be sure to try negative values for baz."}

doc_update(foo, d)

可能有办法将doc_update()变成装饰器,但我现在已经没时间了。

答案 1 :(得分:3)

你想考虑使用decorators干净地做什么~unutbu为函数提出建议:为每个函数添加一个单独的字段。例如:

def human_desc(description):
    def add_field(function):
        function.human_desc = description
        return function
    return add_field

这就是行动human_desc的样子:

@human_desc('This function eggfoobars its spam.')
def eggfoobar(spam):
    "Apply egg, foo and bar to our spam metaclass object stuff."
    print spam

作为the doc explains,该位代码等同于以下内容:

def eggfoobar(spam):
    "Apply egg, foo and bar to our spam metaclass object stuff."
    print spam
eggfoobar = human_desc('This function eggfoobars its spam.')(eggfoobar)

human_desc('This function eggfoobars its spam.')返回以下函数:

def add_field(function):
    function.human_desc = 'This function eggfoobars its spam.'
    return function

正如您所看到的,human_desc是一个函数,它为description的值生成上面的装饰器,并将其作为参数传递。装饰器本身是一个接受要装饰(修改)的函数并返回它修饰的函数(在这种情况下,即添加那些额外的元数据)。简而言之,这相当于:

def eggfoobar(spam):
    "Apply egg, foo and bar to our spam metaclass object stuff."
    print spam
eggfoobar.human_desc = 'This function eggfoobars its spam.'

然而,语法更清晰,更不容易出错。

显然,无论哪种方式,你得到的是:

>>> print eggfoobar.human_desc
This function eggfoobars its spam.

答案 2 :(得分:2)

您可以使用定义了usageextra属性的类,而不是使用函数。例如,

class Foo(object):
    '''Here is the function's official docstring'''
    usage='All about the usage'
    extra='How another part works'
    def __call__(self):
        # Put the foo function code here
        pass
foo=Foo()

你会像往常一样打电话:foo(), 你可以获得正式的文档字符串,以及这样的备用文档字符串:

print foo.__doc__
print foo.usage
print foo.extra

您还可以将附加属性附加到普通函数(而不是像上面那样使用类),但我认为语法有点丑陋:

def foo():
    pass
foo.usage='Usage string'
foo.extra='Extra string'

而且,模块也是对象。他们可以轻松拥有额外的属性:

如果定义模块常量

USAGE='''blah blah'''
EXTRA='''meow'''

然后导入模块时:

import mymodule

您可以使用

访问官方和备用文档字符串
mymodule.__doc__
mymodule.USAGE
mymodule.EXTRA

答案 3 :(得分:0)

如果您想拥有多个可能的文档字符串,可以替换__doc__属性,但请考虑使初始文档字符串足够灵活适用于所有类型。

答案 4 :(得分:0)

模块是类/函数/模块的集合。所以它的docstring给出了它包含的内容的介绍。

类docstring告诉类是什么,它的方法docstrings告诉我们这些方法是什么。一个类有一个目的,一个方法只做一个事情,所以它们应该有单个文档字符串。

函数做一件事,所以一个doctring就足够了。

我看不出多个docstrings的目的是什么。也许你的模块很大。分为子模块和文档字符串中的模块提及子模块。