单个模块/函数等有超过 1 个文档字符串吗?

发布于 2024-08-20 23:28:10 字数 629 浏览 10 评论 0原文

我正在使用 python 3.1。

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

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

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

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

更新:添加了评论。

我最初的想法是实际上拥有多个文档字符串,其含义是:

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

然后我可以使用一些代码来引用每个文档字符串。 那么,我猜这是不可能的?

I'm using python 3.1.

Is it possible to create more than 1 docstring for a single module or function?
I'm creating a program, and I'm intending to have multiple docstrings with a category for each. I intend to give other people the program so they can use it, and to make things easy for programmers and non-programmers alike, I'm putting a reference to the docstring for documentation within the program itself.

To be more specific, I have a menu in the program/module as an interface, and one of the options will allow access to the module docstring for documentation on the program. Thus, if it's possible, I want to make multiple docstrings to categorise different types of documentation. So it would be easier on the users if they want to see some part of the documentation.

eg. first docstring contains instructions on how to use the program. Second docstring contains information on how one part of the program works. Third docstring contains info on how another part works. etc.

Is this possible? And if so, how do you reference them?

Updates: Added a comment.

My original thought was to actually have more than one docstring in the sense of:

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

Then there would be some code that I could use to allow me to reference each of these docstrings.
So, I'm guessing that this isn't possible then?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

粉红×色少女 2024-08-27 23:28:10

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

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

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

I don't recommend trying to do something complicated with the docstrings. Best to keep the docstrings simple, and do something else if you want to make a bunch of different documentation options available.

If you really want to do what you described, I suggest you use tags to delimit sections within docstrings. Like so:

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

Then you can pretty easily split your string into chunks, and when the user chooses a menu item, show just the appropriate chunks.

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

This way, when you are working in the interactive Python shell, you can say "help(foo)" and you will see all the docstrings. And, you are not changing the fundamental behavior of a basic part of Python, which would freak out other people trying to study your code.

You could also do something even simpler: just make a big global dictionary of docstrings for different purposes, and update it from the source code for each new thing.

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."

The biggest thing I don't like about this is that, if you change the name of function foo, you would need to change it in multiple places: once in the actual def and once per dictionary update line. But you could mostly fix that by writing a function:

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)

There is probably a way to turn doc_update() into a decorator, but I'm out of time right now.

痴骨ら 2024-08-27 23:28:10

您需要考虑使用 装饰器 来干净地完成 ~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

解释

As 文档解释了,这段代码相当于以下内容:

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.

You want to consider using decorators to cleanly do what ~unutbu is proposing for functions: adding a separate field per each. For example:

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

This is what human_desc in action would look like:

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

Explaination

As the doc explains, that bit of code is equivalent to the following:

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)

and human_desc('This function eggfoobars its spam.') returns the following function:

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

As you can see human_desc is a function that generates the above decorator for the value of description you pass as an argument. The decorator itself is a function that accepts a function to be decorated (modified) and returns it decorated (in this case, that is, with the addition of that bit of extra metadata). In short this is equivalent to:

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

The syntax, however, is far cleaner and less error prone.

Obviously, in either way, what you get is:

>>> print eggfoobar.human_desc
This function eggfoobars its spam.
帥小哥 2024-08-27 23:28:10

您可以使用定义了 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

Instead of using a function, you could use a class with usage and extra attributes defined. For example,

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()

You'd call it as usual: foo(),
and you can get the official docstring, and alternate doc string like this:

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

You can also attach extra attributes to plain functions (instead of using a class as I did above), but I think the syntax is a little uglier:

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

And, modules are objects too. They can have extra attributes just as easily:

If you define module constants

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

Then when you import the module:

import mymodule

You can access the official and alternate docstrings with

mymodule.__doc__
mymodule.USAGE
mymodule.EXTRA
丑疤怪 2024-08-27 23:28:10

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

You can replace the __doc__ attribute if you want to have more than one possible docstring, but please consider making the initial docstring flexible enough for all types.

野心澎湃 2024-08-27 23:28:10

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

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

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

我不明白多个文档字符串足以满足什么目的。也许你的模块很大。分为子模块,并在模块的文档字符串中提及子模块。

Module is a collection of classes/functions/modules. So its docstring gives the intro about what it contains.

Class docstring tells what the class is about and its methods docstrings tell what the methods so. A class serves one purpose and a methods does a single thing so they should have single docstring.

Functions do one thing so one doctring should suffice for them.

I can't see what purpose will multiple docstrings suffice. Maybe your module is big. Divide into sub-modules and in the docstring for the module mention sub-modules.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文