This question seems to come up regularly both on StackOverflow and elsewhere, yet I wasn't able to find a completely satisfactory solution anywhere.
There seem to be two types of common solutions. The first one (from e.g. http://article.gmane.org/gmane.comp.python.general/630549) uses a function decorator:
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__
This is probably the most straightforward approach, but it requires repeating the parent class name at least once, and also becomes a lot more complicated if the docstring can not be found in the direct ancestor.
The second approach uses a metaclass or class decorator (cf. Inheriting methods' docstrings in Python, Inherit a parent class docstring as __doc__ attribute, http://mail.python.org/pipermail/python-list/2011-June/606043.html) and looks like this:
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__
However, with this approach the docstring is only set after class creation and thus not accessible to decorators, so the following won't work:
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
A third interesting idea has been discussed in Inherit docstrings in Python class inheritance. Here, the function decorator actually wraps the method and turns it into a method descriptor rather than merely updating its docstring. However, this seems like using sledgehammer to crack a nut because it turns the method into a method descriptor (which may have performance implications as well, though I did not check), and also does not make the docstring available to any other decorators (and in the above example will actually make them crash because the method descriptor doesn't have __name__
attribute).
Is there a solution that avoids all the above drawbacks, i.e. does not require me to repeat myself and assigns the docstring immediately using a decorator?
I'm interested in a solution for Python 3.