この質問は、StackOverflowやその他の場所で定期的に出てくるようですが、どこでも完全に満足のいく解決策を見つけることはできませんでした。Python 3 - デコレータを破損することなく、またはDRYに違反することなくdocstring継承する方法
一般的な解決策には2つのタイプがあるようです。 (例えばhttp://article.gmane.org/gmane.comp.python.general/630549から)最初の1は、関数デコレータを使用しています。
class SuperClass:
def my_method(self):
'''Has a docstring'''
pass
class MyClass(SuperClass):
@copy_docstring_from(SuperClass)
def my_method(self):
pass
assert SuperClass.my_method.__doc__ == MyClass.my_method._doc__
これはおそらく最も簡単な方法ですが、それは少なくとも一度は親クラス名を繰り返す必要があり、また、ドキュメンテーション文字列なら、もっと多くの複雑になります直接祖先には見つからない。
第二のアプローチは、メタクラスやクラスのデコレータ(参照Inheriting methods' docstrings in Python、Inherit a parent class docstring as __doc__ attribute、http://mail.python.org/pipermail/python-list/2011-June/606043.html)を使用し、次のようになります。
class MyClass1(SuperClass, metaclass=MagicHappeningHere):
def method(self):
pass
# or
@frobnicate_docstrings
class MyClass2(SuperClass):
def method(self):
pass
assert SuperClass.my_method.__doc__ == MyClass1.my_method._doc__
assert SuperClass.my_method.__doc__ == MyClass2.my_method._doc__
しかし、この方法でドキュメント文字列が唯一のクラスの作成後に設定され、したがって、されていませんデコレータにアクセス可能な、次のように動作しませんので:
def log_docstring(fn):
print('docstring for %s is %s' % (fn.__name__, fn.__doc__)
return fn
class MyClass(SuperClass, metaclass=MagicHappeningHere):
# or
#@frobnicate_docstrings
#class MyClass2(SuperClass):
@log_docstring
def method(self):
pass
第三面白いアイデアはInherit docstrings in Python class inheritanceで議論されてきました。ここでは、関数デコレータは実際にはそのメソッドをラップして、単にそのdocstringを更新するのではなく、メソッド記述子に変換します。しかし、これはsledgehammerを使ってナットをクラックさせるようなものですが、メソッドをメソッド記述子に変換します(これはパフォーマンス上の影響もありますが、チェックしませんでした)。また、docstringを他のデコレータで使用できるようにしません上記の例では、メソッド記述子に__name__
属性がないため、実際にはクラッシュします。
上記の欠点をすべて回避するソリューションがありますか?自分自身を繰り返す必要がなく、デコレータを使用してドキュメントストリングをすぐに割り当てる必要はありませんか?
私は、Python 3
私はこれと少しの巧妙な実装をhttp://code.activestate.com/recipes/578587-inherit-method-docstrings-with-breaking-decorat/に掲載しました。 – Nikratio