(少なくともCPythonでは)クラスに新しいdocstringを割り当てることはできない__doc__
ため、メタクラスを使用する必要があります。
import inspect
def inheritdocstring(name, bases, attrs):
if not '__doc__' in attrs:
# create a temporary 'parent' to (greatly) simplify the MRO search
temp = type('temporaryclass', bases, {})
for cls in inspect.getmro(temp):
if cls.__doc__ is not None:
attrs['__doc__'] = cls.__doc__
break
return type(name, bases, attrs)
はい、余分なフープを1つか2つジャンプしますが、上記のメタクラスは__doc__
、継承グラフを作成する際に、どのように複雑であっても正しいものを見つけます。
使用法:
>>> class ParentWithDocstring(object):
... """Parent docstring"""
...
>>> class SubClassWithoutDocstring(ParentWithDocstring):
... __metaclass__ = inheritdocstring
...
>>> SubClassWithoutDocstring.__doc__
'Parent docstring'
別の方法は、インスタンス変数としてで設定__doc__
することです。__init__
def __init__(self):
try:
self.__doc__ = next(cls.__doc__ for cls in inspect.getmro(type(self)) if cls.__doc__ is not None)
except StopIteration:
pass
次に、少なくともインスタンスにdocstringがあります。
>>> class SubClassWithoutDocstring(ParentWithDocstring):
... def __init__(self):
... try:
... self.__doc__ = next(cls.__doc__ for cls in inspect.getmro(type(self)) if cls.__doc__ is not None)
... except StopIteration:
... pass
...
>>> SubClassWithoutDocstring().__doc__
'Parent docstring'
Python 3.3(問題12773を修正)では、最終的にカスタムクラスの属性を設定できる__doc__
ようになったため、代わりにクラスデコレータを使用できます。
import inspect
def inheritdocstring(cls):
for base in inspect.getmro(cls):
if base.__doc__ is not None:
cls.__doc__ = base.__doc__
break
return cls
このように適用することができます:
>>> @inheritdocstring
... class SubClassWithoutDocstring(ParentWithDocstring):
... pass
...
>>> SubClassWithoutDocstring.__doc__
'Parent docstring'