Inherit docstrings in Python class inheritance

后端 未结 5 2198
难免孤独
难免孤独 2020-12-01 02:25

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:

相关标签:
5条回答
  • 2020-12-01 02:55

    Not particularly elegant, but simple and direct:

    class X(object):
      """This class has a method foo()."""
      def foo(): pass
    
    class Y(X):
      __doc__ = X.__doc__ + ' Also bar().'
      def bar(): pass
    

    Now:

    >>> print Y.__doc__
    This class has a method foo(). Also bar().
    
    0 讨论(0)
  • 2020-12-01 02:55

    I wrote custom_inherit to provide some simple, light weight tools for handling docstring inheritance.

    It also comes with some nice default styles for merging different types of docstrings (e.g. Numpy, Google, and reST formatted docstrings). You can also provide your own style very easily.

    Overlapping docstring sections will defer to the child's section, otherwise they are merged together with nice formatting.

    0 讨论(0)
  • 2020-12-01 02:56

    A mixed stile that can preserve both the inherited docstring syntax and the preferred ordering can be:

    class X(object):
      """This class has a method foo()."""
      def foo(): pass
    
    class Y(X):
      """ Also bar()."""
      __doc__ = X.__doc__ + __doc__
      def bar(): pass
    

    With the same output as Alex's one:

    >>> print Y.__doc__
    This class has a method foo(). Also bar().
    

    Thin ice: playing with docstring can make your module unusable with python -OO, expect some:

    TypeError: cannot concatenate 'str' and 'NoneType' objects
    
    0 讨论(0)
  • 2020-12-01 02:59

    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.

    0 讨论(0)
  • 2020-12-01 03:02

    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 
    
    0 讨论(0)
提交回复
热议问题