Pythonクラス継承でドキュメント文字列を継承する


97

Pythonでいくつかのクラス継承を実行しようとしています。各クラスと継承されたクラスに適切なdocstringが必要です。継承したクラスについては、次のようにしたいと思います。

  • 基本クラスのdocstringを継承します
  • おそらく関連する追加のドキュメントをdocstringに追加します

クラス継承の状況でこの種のdocstring操作を行う(おそらくエレガントまたはpythonic)方法はありますか?多重継承についてはどうですか?


2
質問は残念ながら閉じられていたので回答できませんが、Python 3.5 inspect.getdoc以降では、docstringが見つかるまで継承ツリーを検索します。
gerrit

1
この回答を参照してください。
gerrit

回答:


39

あなただけではありません!comp.lang.pythonしばらく前にこれについての議論があり、レシピが作成されました。それをチェックアウトここに

"""
doc_inherit decorator

Usage:

class Foo(object):
    def foo(self):
        "Frobber"
        pass

class Bar(Foo):
    @doc_inherit
    def foo(self):
        pass 

Now, Bar.foo.__doc__ == Bar().foo.__doc__ == Foo.foo.__doc__ == "Frobber"
"""

from functools import wraps

class DocInherit(object):
    """
    Docstring inheriting method descriptor

    The class itself is also used as a decorator
    """

    def __init__(self, mthd):
        self.mthd = mthd
        self.name = mthd.__name__

    def __get__(self, obj, cls):
        if obj:
            return self.get_with_inst(obj, cls)
        else:
            return self.get_no_inst(cls)

    def get_with_inst(self, obj, cls):

        overridden = getattr(super(cls, obj), self.name, None)

        @wraps(self.mthd, assigned=('__name__','__module__'))
        def f(*args, **kwargs):
            return self.mthd(obj, *args, **kwargs)

        return self.use_parent_doc(f, overridden)

    def get_no_inst(self, cls):

        for parent in cls.__mro__[1:]:
            overridden = getattr(parent, self.name, None)
            if overridden: break

        @wraps(self.mthd, assigned=('__name__','__module__'))
        def f(*args, **kwargs):
            return self.mthd(*args, **kwargs)

        return self.use_parent_doc(f, overridden)

    def use_parent_doc(self, func, source):
        if source is None:
            raise NameError, ("Can't find '%s' in parents"%self.name)
        func.__doc__ = source.__doc__
        return func

doc_inherit = DocInherit 

これは、メソッドが親クラスのメソッドのドキュメント文字列を継承するのに適しています。それは多くの場合に役立つと思います。継承して追加したいクラス全体のdocstringについてもっと考えていました。
Craig McQueen、2010年

ああ、落とし穴。その場合、ほとんどのdoc-generationがすでにそれを行っています。
John Feminella、2010年

36

docstringは簡単に連結できます。

class Foo(object):
    """
    Foo Class.
    This class foos around.
    """
    pass

class Bar(Foo):
    """
    Bar class, children of Foo
    Use this when you want to Bar around.
    parent:
    """ 
    __doc__ += Foo.__doc__
    pass

しかし、それは無意味です。ほとんどのドキュメント生成ツール(SphinxEpydocが含まれています)は、メソッドを含め、すでに親docstringをプルします。したがって、何もする必要はありません。


16
実際、ほとんどのドキュメンテーションツールはそれを行います。しかし、組み込みのhelp()関数はサポートしていません。
MarioVilas 2013年

2
@MarioVilas:おそらくそれは報告すべきバグでしょうか?
naught101

Sphinxは私のためにそれをしていないようです、おそらく私の親は「プライベート」であるので、別名名前はアンダースコアで始まります。
Gringo Suave

6

特にエレガントではありませんが、シンプルで直接的です。

class X(object):
  """This class has a method foo()."""
  def foo(): pass

class Y(X):
  __doc__ = X.__doc__ + ' Also bar().'
  def bar(): pass

今:

>>> print Y.__doc__
This class has a method foo(). Also bar().

あなたInit docstringも同様にこれをしたい場合は、の定義でそれを行う方法はありYますか?私がそれを行うことができた唯一の方法__init__.__doc__ = X.__init__.__doc__ + " Also another param"はの__init__定義に従って使用することですYが、これは書式設定を混乱させ、余分なスペースを追加するようです。
mgilbert 2017年

5

継承されたdocstring構文と優先順序の両方を保持できる混合スタイルは次のとおりです。

class X(object):
  """This class has a method foo()."""
  def foo(): pass

class Y(X):
  """ Also bar()."""
  __doc__ = X.__doc__ + __doc__
  def bar(): pass

アレックスのものと同じ出力で:

>>> print Y.__doc__
This class has a method foo(). Also bar().

薄い氷: docstringで遊ぶと、モジュールがで使用できなくなる可能性がありますpython -OO

TypeError: cannot concatenate 'str' and 'NoneType' objects

4

私が書いたcustom_inheritをドキュメンテーション文字列の継承を処理するためのいくつかの簡単な、軽量のツールを提供します。

また、さまざまなタイプのドキュメント文字列(Numpy、Google、およびreST形式のドキュメント文字列など)をマージするための、いくつかの素晴らしいデフォルトスタイルも付属しています。独自のスタイルを非常に簡単に提供することもできます。

重複するdocstringセクションは子のセクションに従います。それ以外の場合は、素敵なフォーマットでマージされます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.