この質問は、StackOverflow と他の場所の両方で定期的に出てくるようですが、完全に満足できる解決策をどこにも見つけることができませんでした。
一般的なソリューションには 2 つのタイプがあるようです。最初のもの (例えばhttp://article.gmane.org/gmane.comp.python.general/630549から) は関数デコレータを使用します:
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__
これはおそらく最も簡単な方法ですが、親クラス名を少なくとも 1 回繰り返す必要があり、直接の祖先に docstring が見つからない場合はさらに複雑になります。
2 番目のアプローチでは、メタクラスまたはクラス デコレータを使用します ( Pythonでメソッドのドキュメント文字列を継承する、親クラスのドキュメント文字列を __doc__ 属性として継承する、 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__
ただし、このアプローチでは、docstring はクラスの作成後にのみ設定されるため、デコレーターはアクセスできないため、次の方法は機能しません。
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
3 つ目の興味深いアイデアは、Python クラスの継承でドキュメント文字列を継承する で説明されています。ここで、関数デコレータは、単にドキュメント文字列を更新するのではなく、実際にメソッドをラップしてメソッド記述子に変換します。ただし、これはメソッドをメソッド記述子に変換するため (私は確認していませんが、パフォーマンスに影響を与える可能性があります)、ドキュメント文字列を他のデコレータ (および上記の例では、メソッド記述子に属性がないため、実際にはクラッシュし__name__
ます)。
上記のすべての欠点を回避する解決策はありますか?
Python 3 のソリューションに興味があります。