5

私はpython 3.1を使用しています。

1 つのモジュールまたは関数に対して複数の docstring を作成することは可能ですか? 私はプログラムを作成しており、それぞれにカテゴリを持つ複数の docstring を持つつもりです。私は他の人がプログラムを使用できるようにプログラムを提供するつもりです。また、プログラマーと非プログラマーの両方にとって物事を簡単にするために、プログラム自体のドキュメント用の docstring への参照を入れています。

より具体的には、プログラム/モジュールにインターフェイスとしてメニューがあり、オプションの1つを使用して、プログラムに関するドキュメントのモジュールdocstringにアクセスできます。したがって、可能であれば、複数のドキュメント文字列を作成して、さまざまな種類のドキュメントを分類したいと考えています。そのため、ドキュメントの一部を見たい場合は、ユーザーにとってより簡単になります。

例えば。最初の docstring には、プログラムの使用方法に関する説明が含まれています。2 番目の docstring には、プログラムの一部がどのように機能するかに関する情報が含まれています。3 番目の docstring には、別の部分がどのように機能するかに関する情報が含まれています。等

これは可能ですか?もしそうなら、どのようにそれらを参照しますか?

更新: コメントを追加しました。

私の最初の考えは、実際には次の意味で複数のdocstringを持つことでした:

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

次に、これらの各 docstring を参照できるようにするために使用できるコードがいくつかあります。それで、これは不可能だと思いますか?

4

5 に答える 5

5

docstring で複雑なことをしようとすることはお勧めしません。docstring をシンプルに保ち、さまざまなドキュメント オプションを利用可能にしたい場合は別のことを行うのが最善です。

説明したことを本当にやりたい場合は、タグを使用してドキュメントストリング内のセクションを区切ることをお勧めします。そのようです:

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 シェルで作業しているときに、「help(foo)」と言うと、すべての docstring が表示されます。また、Python の基本的な部分の基本的な動作を変更していないため、コードを研究しようとしている他の人を驚かせることにもなりません。

もっと単純なこともできます: さまざまな目的のために docstring の大きなグローバル ディクショナリを作成し、新しいものごとにソース コードから更新するだけです。

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行で 1 回、辞書の更新行ごとに 1 回です。しかし、ほとんどの場合、関数を書くことでそれを修正できます:

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

公式および代替のdocstringにアクセスするには、

mymodule.__doc__
mymodule.USAGE
mymodule.EXTRA
于 2010-02-13T19:43:24.420 に答える
1

__doc__複数の可能性のある docstring が必要な場合は、属性を置き換えることができますが、最初の docstring をすべてのタイプに対して十分に柔軟にすることを検討してください。

于 2010-02-13T19:21:06.247 に答える
1

モジュールは、クラス/関数/モジュールのコレクションです。したがって、その docstring は、その内容についてのイントロを提供します。

クラス docstring はクラスが何であるかを示し、そのメソッド docstrings はメソッドが何であるかを示します。クラスは 1 つの目的を果たし、メソッドは 1 つのことを行うため、1 つの docstring を持つ必要があります。

関数は 1 つのことを行うので、1 つの doctring で十分です。

複数のdocstringで十分な目的がわかりません。多分あなたのモジュールは大きいです。サブモジュールに分割し、モジュールのドキュメント文字列でサブモジュールについて言及します。

于 2010-02-13T19:23:30.540 に答える