python - 继承父类文档字符串作为 __doc__ 属性

标签 python docstring django-rest-framework

有一个关于Inherit docstrings in Python class inheritance的问题,但那里的答案涉及方法文档字符串。

我的问题是如何继承父类的文档字符串作为 __doc__ 属性。用例是 Django rest framework根据您的 View 类的文档字符串,在您的 API 的 html 版本中生成很好的文档。但是在没有文档字符串的类中继承基类(带有文档字符串)时,API 不显示文档字符串。

很可能是 sphinx 和其他工具做正确的事情并为我处理文档字符串继承,但 django rest 框架查看(空).__doc__ 属性。

class ParentWithDocstring(object):
    """Parent docstring"""
    pass


class SubClassWithoutDoctring(ParentWithDocstring):
    pass


parent = ParentWithDocstring()
print parent.__doc__  # Prints "Parent docstring".
subclass = SubClassWithoutDoctring()
print subclass.__doc__  # Prints "None"

我已经尝试过像 super(SubClassWithoutDocstring, self).__doc__ 这样的东西,但它也只给我一个 None

最佳答案

由于您不能将新的 __doc__ 文档字符串分配给一个类(至少在 CPython 中),您将不得不使用元类:

import inspect

def inheritdocstring(name, bases, attrs):
    if not '__doc__' in attrs:
        # create a temporary 'parent' to (greatly) simplify the MRO search
        temp = type('temporaryclass', bases, {})
        for cls in inspect.getmro(temp):
            if cls.__doc__ is not None:
                attrs['__doc__'] = cls.__doc__
                break

    return type(name, bases, attrs)

是的,我们跳过了一两个额外的圈,但是上面的元类将找到正确的 __doc__ 无论您制作继承图有多复杂。

用法:

>>> class ParentWithDocstring(object):
...     """Parent docstring"""
... 
>>> class SubClassWithoutDocstring(ParentWithDocstring):
...     __metaclass__ = inheritdocstring
... 
>>> SubClassWithoutDocstring.__doc__
'Parent docstring'

另一种方法是将__init__中的__doc__设置为实例变量:

def __init__(self):
    try:
        self.__doc__ = next(cls.__doc__ for cls in inspect.getmro(type(self)) if cls.__doc__ is not None)
    except StopIteration:
        pass

那么至少你的实例有一个文档字符串:

>>> class SubClassWithoutDocstring(ParentWithDocstring):
...     def __init__(self):
...         try:
...             self.__doc__ = next(cls.__doc__ for cls in inspect.getmro(type(self)) if cls.__doc__ is not None)
...         except StopIteration:
...             pass
... 
>>> SubClassWithoutDocstring().__doc__
'Parent docstring'

从 Python 3.3(已修复 issue 12773)开始,您可以最终只设置自定义类的 __doc__ 属性,这样您就可以改用类装饰器:

import inspect

def inheritdocstring(cls):
    for base in inspect.getmro(cls):
        if base.__doc__ is not None:
            cls.__doc__ = base.__doc__
            break
    return cls

然后可以这样应用:

>>> @inheritdocstring
... class SubClassWithoutDocstring(ParentWithDocstring):
...     pass
... 
>>> SubClassWithoutDocstring.__doc__
'Parent docstring'

关于python - 继承父类文档字符串作为 __doc__ 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13937500/

相关文章:

python - pytest.raises 失败 : DID NOT RAISE with try/except

python-sphinx - Python 代码中注释和文档字符串的基本语法

python - 通过 POST 请求返回列表

python - 使用序列化器作为查询参数验证器是一个好习惯吗?

python - 打开 CSV,对特定列进行排序并覆盖现有 CSV

python - 将 JSON 转换为 QGIS GeoJSON : while having multiple features and different types

python - 类型错误 : 'encoding' while installing CairoSVG and WeazyPrint on Python 2. 7

python - 文档字符串与评论

python - 知道函数不接受来自文档字符串的命名参数

django - ModelSerializer.update() 和 ModelViewSet.update() 之间的区别