【问题标题】:How do I document a constructor for a class using Python dataclasses?如何使用 Python 数据类记录类的构造函数?
【发布时间】:2018-12-10 01:07:04
【问题描述】:

我有一些现有的 Python 3.6 代码,我想转移到 Python 3.7 数据类。我有 __init__ 方法和很好的文档字符串文档,指定构造函数采用的属性及其类型。

但是,如果我将这些类更改为使用 3.7 中的新 Python 数据类,则构造函数是隐式的。在这种情况下,我如何提供构造函数文档?我喜欢数据类的想法,但如果我必须放弃清晰的文档才能使用它们。

已编辑以澄清我目前正在使用文档字符串

【问题讨论】:

  • 似乎数据类会自动为包含类定义中的类型提示的类生成一个文档字符串,例如'C(name: str, number: int)',但自动生成的__init__方法的文档字符串是None。所以我想你可以在类定义之后手动分配__init__ 文档字符串。不过有点笨重。
  • 如果我在课堂上已经有一个文档字符串,那么这个自动生成的文档字符串不会显示出来,这很好,因为人工提供的文档字符串(通常!)比自动生成的要好得多。手动分配文档字符串绝对是笨拙的,如果可能的话我想避免,因此这个问题。
  • 两点都正确。此外,手动分配的文档字符串适用于 help 等运行时工具,但可能不适用于 Sphinx 等文档生成器。

标签: python documentation python-3.7 docstring python-dataclasses


【解决方案1】:

我认为最简单的方法是:

@dataclass
class TestClass:
    """This is a test class for dataclasses.

    This is the body of the docstring description.

    """
    var_int: int  #: An integer.

    #: A string.
    #: (Able to have multiple lines.)
    var_str: str

    var_float: float
    """A float. (Able to have multiple lines.)"""

不知道为什么@Arne 渲染的结果看起来像这样。就我而言,无论文档字符串如何,数据类中的属性都将始终显示。那就是:

1) 最低限度:

2) 附加构造函数参数说明:

3) 附加属性说明:

可能是因为我在我的conf.py(Sphinx v3.4.3,Python 3.7)中设置了错误:

extensions = [
    "sphinx.ext.napoleon",
    "sphinx.ext.autodoc",
    "sphinx_autodoc_typehints",
    "sphinx.ext.viewcode",
    "sphinx.ext.autosectionlabel",
]

# Napoleon settings
napoleon_google_docstring = True
napoleon_include_init_with_doc = True

【讨论】:

【解决方案2】:

the sphinx docs 中描述的拿破仑风格的文档字符串(请参阅ExampleError 类了解他们对此的看法)明确涉及您的案例:

__init__ 方法可以记录在类级别的文档字符串中,或​​者作为 __init__ 方法本身的文档字符串。

如果你不想要这种行为,你必须explicitly tell sphinx构造函数文档字符串和类文档字符串不是一回事。

意思是,您可以将构造函数信息粘贴到类文档字符串的主体中。


如果您从文档字符串构建文档,这些是可以实现的粒度:

1) 最低限度:

@dataclass
class TestClass:
    """This is a test class for dataclasses.

    This is the body of the docstring description.
    """
    var_int: int
    var_str: str

2) 附加构造函数参数说明:

@dataclass
class TestClass:
    """This is a test class for dataclasses.

    This is the body of the docstring description.

    Args:
        var_int (int): An integer.
        var_str (str): A string.

    """
    var_int: int
    var_str: str

3) 附加属性说明:

@dataclass
class TestClass:
    """This is a test class for dataclasses.

    This is the body of the docstring description.

    Attributes:
        var_int (int): An integer.
        var_str (str): A string.

    """
    var_int: int
    var_str: str


参数和属性描述当然也可以结合起来,但是由于数据类应该是直接的映射,我认为没有理由这样做。

在我看来,1) 适用于小型或简单的数据类——它已经包含了构造函数签名及其各自的类型,这对于数据类来说已经足够了。如果您想详细说明每个属性,3) 会是最好的选择。

【讨论】:

  • 这篇文章非常深入,谢谢!我特别感谢对 Sphinx 文档的引用,这些文档正好涵盖了这种情况。
  • 很高兴它对你有帮助 =)
  • @Arne 兄弟,您使用的 Sphinx 配置是什么?我无法像您的第三个示例那样生成属性文档。
  • @woozly 我只是重新运行了我认为是我的示例 cpde,但我无法让它们看起来相同。也许 sphinx 改变了他们对待数据类的方式?无论如何,我的conf.pys 看起来都或多或少like this(只需将主题切换到"alabaster" 以查看此处的帖子),并且文档已构建as described here
  • @Arne 谢谢!我已经启用了sphinx.ext.napoleon 扩展。
【解决方案3】:

数据类的一个主要优点是它们是自记录的。假设你的代码的读者知道数据类是如何工作的(并且你的属性被适当地命名),类型注释的类属性应该是构造函数的优秀文档。这个例子见官方dataclass docs

@dataclass
class InventoryItem:
    '''Class for keeping track of an item in inventory.'''
    name: str
    unit_price: float
    quantity_on_hand: int = 0

    def total_cost(self) -> float:
        return self.unit_price * self.quantity_on_hand

如果您不希望代码的读者知道数据类是如何工作的,那么您可能需要重新考虑使用它们,或者在 @dataclass 装饰器之后的内联注释中添加解释或文档链接。如果您确实需要数据类的文档字符串,我建议将构造函数文档字符串放在类文档字符串中。对于上面的例子:

'''Class for keeping track of an item in inventory.

Constructor arguments:
:param name: name of the item
:param unit_price: price in USD per unit of the item
:param quantity_on_hand: number of units currently available
'''

【讨论】:

  • 嗯。如果它们真的要自我记录,这将更加强调命名属性的重要性。感谢您的建议!
  • @orn688 但是是否有可能从文档中完全消除dataclass
  • 值得注意的是help(InventoryItem)显示属性nameunit_pricequantity_on_hand或其文档字符串。
猜你喜欢
  • 2019-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-19
  • 1970-01-01
相关资源
最近更新 更多