5

我正在使用python 3.1。

是否可以为单个模块或函数创建超过 1 个文档字符串?我正在创建一个程序,并且我打算有多个文档字符串,每个文档字符串都有一个类别。我打算将程序提供给其他人,以便他们可以使用它,并且为了让程序员和非程序员都可以轻松使用,我在程序本身中引用了文档字符串以供文档使用。

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

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

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

更新:添加了评论。

我最初的想法是实际上有多个文档字符串:

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

然后会有一些代码可以让我引用这些文档字符串中的每一个。所以,我猜这不可能吗?

4

5 回答 5

5

我不建议尝试使用文档字符串做一些复杂的事情。最好保持文档字符串简单,如果您想提供一堆不同的文档选项,请执行其他操作。

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

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() 变成装饰器,但我现在没时间了。

于 2010-02-13T19:57:32.023 回答
4

您想考虑使用装饰器来干净地执行 ~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

解释

正如文档解释的那样,那段代码等效于以下内容:

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.
于 2010-02-13T20:00:24.530 回答
3

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

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
于 2010-02-13T19:43:24.420 回答
1

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

于 2010-02-13T19:21:06.247 回答
1

模块是类/函数/模块的集合。所以它的文档字符串给出了它包含的内容的介绍。

类文档字符串告诉类是关于什么的,它的方法文档字符串告诉了方法是什么。一个类有一个目的,一个方法只做一件事,所以它们应该有一个文档字符串。

函数只做一件事,所以一个文档就足够了。

我看不出多个文档字符串能满足什么目的。也许你的模块很大。划分为子模块并在模块的文档字符串中提及子模块。

于 2010-02-13T19:23:30.540 回答