这个问题似乎经常出现在 StackOverflow 和其他地方,但我无法在任何地方找到完全令人满意的解决方案。
似乎有两种常见的解决方案。第一个(来自例如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__
这可能是最直接的方法,但它需要至少重复一次父类名称,如果在直接祖先中找不到文档字符串,也会变得更加复杂。
第二种方法使用元类或类装饰器(参见在 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__
但是,使用这种方法,文档字符串仅在类创建之后设置,因此装饰器无法访问,因此以下内容将不起作用:
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
在 Python 类继承中的 Inherit docstrings 中讨论了第三个有趣的想法。在这里,函数装饰器实际上包装了方法并将其转换为方法描述符,而不仅仅是更新其文档字符串。然而,这似乎是使用大锤来破解一个坚果,因为它把方法变成了一个方法描述符(这可能也有性能影响,虽然我没有检查),并且也不使文档字符串可用于任何其他装饰器(和在上面的例子中实际上会使它们崩溃,因为方法描述符没有__name__
属性)。
是否有一种解决方案可以避免上述所有缺点,即不需要我重复自己并使用装饰器立即分配文档字符串?
我对 Python 3 的解决方案感兴趣。