Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inherit docstrings in Python class inheritance

I'm trying to do some class inheritance in Python. I'd like each class and inherited class to have good docstrings. So I think for the inherited class, I'd like it to:

  • inherit the base class docstring
  • maybe append relevant extra documentation to the docstring

Is there any (possibly elegant or pythonic) way of doing this sort of docstring manipulation in a class inheritance situation? How about for multiple inheritance?

like image 589
Craig McQueen Avatar asked Jan 08 '10 04:01

Craig McQueen


People also ask

Are docstrings inherited?

Docstring sections are inherited individually, like methods for a classes.

How do you use docstrings in Python?

Declaring Docstrings: The docstrings are declared using ”'triple single quotes”' or “””triple double quotes””” just below the class, method or function declaration. All functions should have a docstring.

Can docstrings be assigned to variables?

Yes, you can do that! You can actually 'document' lambdas and variables in a module by attaching docstrings to them.

What are the three types of docstrings?

Let us know the most commonly used docstring formats out there in the wild, which are namely- Google, NumPy, and Sphinx docstring formats.


2 Answers

You're not the only one! There was a discussion on comp.lang.python about this a while ago, and a recipe was created. Check it out here.

""" doc_inherit decorator  Usage:  class Foo(object):     def foo(self):         "Frobber"         pass  class Bar(Foo):     @doc_inherit     def foo(self):         pass   Now, Bar.foo.__doc__ == Bar().foo.__doc__ == Foo.foo.__doc__ == "Frobber" """  from functools import wraps  class DocInherit(object):     """     Docstring inheriting method descriptor      The class itself is also used as a decorator     """      def __init__(self, mthd):         self.mthd = mthd         self.name = mthd.__name__      def __get__(self, obj, cls):         if obj:             return self.get_with_inst(obj, cls)         else:             return self.get_no_inst(cls)      def get_with_inst(self, obj, cls):          overridden = getattr(super(cls, obj), self.name, None)          @wraps(self.mthd, assigned=('__name__','__module__'))         def f(*args, **kwargs):             return self.mthd(obj, *args, **kwargs)          return self.use_parent_doc(f, overridden)      def get_no_inst(self, cls):          for parent in cls.__mro__[1:]:             overridden = getattr(parent, self.name, None)             if overridden: break          @wraps(self.mthd, assigned=('__name__','__module__'))         def f(*args, **kwargs):             return self.mthd(*args, **kwargs)          return self.use_parent_doc(f, overridden)      def use_parent_doc(self, func, source):         if source is None:             raise NameError, ("Can't find '%s' in parents"%self.name)         func.__doc__ = source.__doc__         return func  doc_inherit = DocInherit  
like image 86
John Feminella Avatar answered Nov 13 '22 14:11

John Feminella


You can concatenate the docstrings easily:

class Foo(object):     """     Foo Class.     This class foos around.     """     pass  class Bar(Foo):     """     Bar class, children of Foo     Use this when you want to Bar around.     parent:     """      __doc__ += Foo.__doc__     pass 

However, that is useless. Most documentation generation tool (Sphinx and Epydoc included) will already pull parent docstring, including for methods. So you don't have to do anything.

like image 36
nosklo Avatar answered Nov 13 '22 13:11

nosklo