Pythonでいくつかのクラス継承を実行しようとしています。各クラスと継承されたクラスに適切なdocstringが必要です。継承したクラスについては、次のようにしたいと思います。
- 基本クラスのdocstringを継承します
- おそらく関連する追加のドキュメントをdocstringに追加します
クラス継承の状況でこの種のdocstring操作を行う(おそらくエレガントまたはpythonic)方法はありますか?多重継承についてはどうですか?
Pythonでいくつかのクラス継承を実行しようとしています。各クラスと継承されたクラスに適切なdocstringが必要です。継承したクラスについては、次のようにしたいと思います。
クラス継承の状況でこの種のdocstring操作を行う(おそらくエレガントまたはpythonic)方法はありますか?多重継承についてはどうですか?
回答:
あなただけではありません!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は簡単に連結できます。
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
しかし、それは無意味です。ほとんどのドキュメント生成ツール(SphinxとEpydocが含まれています)は、メソッドを含め、すでに親docstringをプルします。したがって、何もする必要はありません。
特にエレガントではありませんが、シンプルで直接的です。
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
が、これは書式設定を混乱させ、余分なスペースを追加するようです。
継承された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
私が書いたcustom_inheritをドキュメンテーション文字列の継承を処理するためのいくつかの簡単な、軽量のツールを提供します。
また、さまざまなタイプのドキュメント文字列(Numpy、Google、およびreST形式のドキュメント文字列など)をマージするための、いくつかの素晴らしいデフォルトスタイルも付属しています。独自のスタイルを非常に簡単に提供することもできます。
重複するdocstringセクションは子のセクションに従います。それ以外の場合は、素敵なフォーマットでマージされます。
inspect.getdoc
以降では、docstringが見つかるまで継承ツリーを検索します。