145

私は、属性がパブリックにアクセス可能であり、特定のインスタンス化でオーバーライドされることがある軽量クラスを作成しています。Python 言語には、クラス属性の docstring やその他の属性を作成するための規定はありません。これらの属性を文書化するために、期待され、サポートされている方法は何ですか? 現在、私はこのようなことをしています:

class Albatross(object):
    """A bird with a flight speed exceeding that of an unladen swallow.

    Attributes:
    """

    flight_speed = 691
    __doc__ += """
        flight_speed (691)
          The maximum speed that such a bird can attain.
    """

    nesting_grounds = "Raymond Luxury-Yacht"
    __doc__ += """
        nesting_grounds ("Raymond Luxury-Yacht")
          The locale where these birds congregate to reproduce.
    """

    def __init__(self, **keyargs):
        """Initialize the Albatross from the keyword arguments."""
        self.__dict__.update(keyargs)

これにより、最初の標準ドキュメント文字列セクションを含むクラスのドキュメント文字列と、 への拡張代入を介して各属性に追加された行が生成されます__doc__

このスタイルはdocstring スタイル ガイドラインで明示的に禁止されているようには見えませんが、オプションとしても言及されていません。ここでの利点は、提示可能なクラス docstring を作成しながら、定義と共に属性を文書化する方法を提供し、docstring からの情報を繰り返すコメントを記述する必要がないことです。属性を実際に 2 回書かなければならないことに、いまだにイライラしています。少なくともデフォルト値の重複を避けるために、docstring の値の文字列表現を使用することを検討しています。

これは、その場しのぎのコミュニティの慣習に対する凶悪な違反ですか? 大丈夫ですか?より良い方法はありますか?たとえば、属性の値とドキュメント文字列を含むディクショナリを作成し、その内容を__dict__クラス宣言の末尾に向かってクラスとドキュメント文字列に追加することができます。これにより、属性名と値を 2 回入力する必要がなくなります。 edit : この最後のアイデアは、少なくともデータからクラス全体を動的に構築しない限り、実際には不可能だと思います。これは、他の理由がない限り、本当に悪い考えのように思えます。

私は python にかなり慣れていないので、コーディング スタイルの詳細をまだ調べているので、関係のない批評も大歓迎です。

4

4 に答える 4

112

混乱を避けるために:プロパティという用語は、Pythonでは特定の意味を持ちます。あなたが話しているのは、私たちがクラス属性と呼んでいるものです。それらは常にクラスを通じて作用されるため、クラスのドキュメント文字列内にそれらを文書化することが理にかなっていることがわかりました。このようなもの:

class Albatross(object):
    """A bird with a flight speed exceeding that of an unladen swallow.

    Attributes:
        flight_speed     The maximum speed that such a bird can attain.
        nesting_grounds  The locale where these birds congregate to reproduce.
    """
    flight_speed = 691
    nesting_grounds = "Throatwarbler Man Grove"

あなたの例のアプローチよりも目に優しいと思います。属性値のコピーを doc 文字列に表示したい場合は、各属性の説明の横または下に配置します。

Python では、doc 文字列は、単なるソース コードの注釈ではなく、文書化されたオブジェクトの実際のメンバーであることに注意してください。クラス属性変数はオブジェクト自体ではなく、オブジェクトへの参照であるため、独自のドキュメント文字列を保持する方法がありません。おそらく「実際にここにあるもの」ではなく「ここにあるもの」を説明するために、参照に関するドキュメント文字列のケースを作成できると思いますが、それを含むクラスのドキュメント文字列でそれを行うのは簡単だと思います。

于 2010-06-16T07:25:10.473 に答える
37

PEP257: Docstring Conventions を引用します。Docstringとは何ですかというセクションで次のように述べられています。

Python コードの他の場所で発生する文字列リテラルもドキュメントとして機能する場合があります。これらは Python バイトコード コンパイラによって認識されず、ランタイム オブジェクト属性としてアクセスできません (つまり、__doc__ に割り当てられません)。ただし、2 種類の余分な docstring がソフトウェア ツールによって抽出される場合があります。

モジュール、クラス、または __init__ メソッドのトップレベルでの単純な割り当ての直後に発生する文字列リテラルは、「属性ドキュメント文字列」と呼ばれます。

これは PEP 258: Attribute docstrings で詳しく説明されています。上で説明したように ʇsәɹoɈ. 属性は __doc__ を所有できるオブジェクトではないため、help()または pydoc には表示されません。これらの docstring は、生成されたドキュメントにのみ使用できます。

Sphinx でautoattribute ディレクティブ とともに使用されます。

Sphinx は、割り当ての前の行にコメントを使用したり、割り当ての後に特別なコメントを使用したり、自動文書化される定義の後に docstring を使用したりできます。

于 2012-03-04T20:52:28.350 に答える
19

この効果のためにプロパティを悪用する可能性があります。プロパティには、getter、setter、deleter、および docstringが含まれます。単純に、これは非常に冗長になります。

class C:
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """Docstring goes here."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

次に、Cx に属する docstring を取得します。

In [24]: print(C.x.__doc__)
Docstring goes here.

多くの属性に対してこれを行うのは面倒ですが、ヘルパー関数 myprop を思い描くことができます:

def myprop(x, doc):
    def getx(self):
        return getattr(self, '_' + x)

    def setx(self, val):
        setattr(self, '_' + x, val)

    def delx(self):
        delattr(self, '_' + x)

    return property(getx, setx, delx, doc)

class C:
    a = myprop("a", "Hi, I'm A!")
    b = myprop("b", "Hi, I'm B!")

In [44]: c = C()

In [46]: c.b = 42

In [47]: c.b
Out[47]: 42

In [49]: print(C.b.__doc__)
Hi, I'm B!

次に、Pythons interactive を呼び出すと、次のhelpようになります。

Help on class C in module __main__:

class C
 |  Data descriptors defined here:
 |  
 |  a
 |      Hi, I'm A!
 |  
 |  b
 |      Hi, I'm B!

これは、あなたが求めているものとほぼ同じであるべきだと思います。

編集myprop:内部名は重要ではないため、最初の引数をまったく渡す必要をおそらく回避できることがわかりました。の後続の呼び出しmypropが何らかの方法で相互に通信できる場合、長くてありそうもない内部属性名が自動的に決定される可能性があります。これを実装する方法があると確信していますが、それだけの価値があるかどうかはわかりません。

于 2013-03-20T23:55:03.753 に答える
8

他の答えは非常に時代遅れです。PEP-224 (Python 2.1 で利用可能!) には、属性に docstring を使用する方法が説明されています。奇妙なことに、それらは属性のに来ます。

class C:
    "class C doc-string"

    a = 1
    "attribute C.a doc-string (1)"

    b = 2
    "attribute C.b doc-string (2)"

次のような型注釈にも機能します。

class C:
    "class C doc-string"

    a: int
    "attribute C.a doc-string (1)"

    b: str
    "attribute C.b doc-string (2)"

VSCode はこれらの表示をサポートしています。

于 2021-10-28T13:13:11.400 に答える