在Python类继承中继承文档字符串


97

我正在尝试在Python中进行一些类继承。我希望每个类和继承的类都具有良好的文档字符串。因此,我认为对于继承的类,我希望这样做:

  • 继承基类文档字符串
  • 也许将相关的额外文档附加到文档字符串中

在类继承情况下,是否有任何(可能是优雅的或pythonic的)方式来进行这种文档字符串操作?多重继承怎么样?


2
我无法回答,因为问题很遗憾已关闭,但是从Python 3.5开始,inspect.getdoc它将搜索继承树,直到找到文档字符串。
gerrit

1
看到这个答案
Gerrit

Answers:


39

你并不是唯一的一个!comp.lang.python前段时间对此进行了讨论,并创建了一个配方。检查它在这里

"""
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 

对于继承父类的方法的文档字符串的方法而言,这很干净。我认为在许多情况下这将很有用。我在考虑整个类的文档字符串,我想在其中继承和追加。
克雷格·麦昆

啊,知道了 在这种情况下,大多数文档生成者已经为您完成了此任务。
约翰·费米内拉

36

您可以轻松地连接文档字符串:

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

但是,这是没有用的。大多数文档生成工具(包括SphinxEpydoc)将已经提取父文档字符串,包括用于方法的文档字符串。因此,您无需执行任何操作。


16
确实,大多数文档工具都这样做。但是内置的help()函数没有。
MarioVilas

2
@MarioVilas:也许应该报告这个错误?
naught101 '09

Sphinx似乎并没有为我这样做,也许是因为我的父母是“私人”,又名以下划线开头。
Gringo Suave

6

不是特别优雅,但简单直接:

class X(object):
  """This class has a method foo()."""
  def foo(): pass

class Y(X):
  __doc__ = X.__doc__ + ' Also bar().'
  def bar(): pass

现在:

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

如果您也想这样做Init docstring,是否可以在的定义中进行Y呢?我能够做到的唯一方法是使用中__init__.__doc__ = X.__init__.__doc__ + " Also another param"__init__定义,Y但这似乎与格式混淆,导致额外的空格。
mgilbert

5

既可以保留继承的文档字符串语法又可以保留首选顺序的混合阶梯可以是:

class X(object):
  """This class has a method foo()."""
  def foo(): pass

class Y(X):
  """ Also bar()."""
  __doc__ = X.__doc__ + __doc__
  def bar(): pass

与Alex的输出相同:

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

轻而易举:使用docstring会使您的模块无法使用python -OO,请期待:

TypeError: cannot concatenate 'str' and 'NoneType' objects

4

我编写了custom_inherit,以提供一些简单,轻量级的工具来处理文档字符串继承。

它还带有一些不错的默认样式,用于合并不同类型的文档字符串(例如Numpy,Google和reST格式的文档字符串)。您还可以轻松提供自己的样式。

重叠的文档字符串部分将遵循子部分,否则它们将以良好的格式合并在一起。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.