<p>由于无法将新的<code>__doc__</code>docstring赋给类(至少在CPython中),因此必须使用元类:</p>
<pre><code>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)
</code></pre>
<p>是的,我们会跳过一两个额外的圈,但是上面的元类会找到正确的<code>__doc__</code>,不管您的继承图如何复杂。</p>
<p>用法:</p>
<pre><code>>>> class ParentWithDocstring(object):
... """Parent docstring"""
...
>>> class SubClassWithoutDocstring(ParentWithDocstring):
... __metaclass__ = inheritdocstring
...
>>> SubClassWithoutDocstring.__doc__
'Parent docstring'
</code></pre>
<p>另一种方法是将<code>__init__</code>中的<code>__doc__</code>设置为实例变量:</p>
<pre><code>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
</code></pre>
<p>那么至少你的实例有一个docstring:</p>
<pre><code>>>> 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'
</code></pre>
<p>从Python 3.3(它修复了<a href="http://bugs.python.org/issue12773" rel="noreferrer">issue 12773</a>)开始,您可以<em>最终只设置自定义类的<code>__doc__</code>属性,这样您就可以使用类装饰器代替:</p>
<pre><code>import inspect
def inheritdocstring(cls):
for base in inspect.getmro(cls):
if base.__doc__ is not None:
cls.__doc__ = base.__doc__
break
return cls
</code></pre>
<p>因此可以应用于:</p>
<pre><code>>>> @inheritdocstring
... class SubClassWithoutDocstring(ParentWithDocstring):
... pass
...
>>> SubClassWithoutDocstring.__doc__
'Parent docstring'
</code></pre>