Python的Sphinx中,var、cvar和ivar有什么区别?

19

我正在阅读Sphinx文档页面时,讽刺的是我发现有关var、ivar和cvar之间区别的文档非常缺乏。我想知道是否有人能够解释内联代码中每个不同命名空间之间的区别。

示例:

class foo(object):
    """
      :var str first:
      :ivar str last:
      :cvar str middle:
    """

这些sphinx标签各自有何不同,我应该如何知道哪一个是正确的,并按设计使用它们?

3个回答

25

var 是一个通用变量。当你记录文档时,如果你不想对变量做进一步的区分,就可以使用它。

ivar 是指"实例变量",即在实例对象上设置的变量(类的实例)。通常情况下,这些会在__init__方法中(在Python中)定义。

cvar 是指"类变量",即直接在类对象上设置的变量。通常情况下,这些会在类语句中设置,但在类的任何特定方法之外。

以下是一个示例:

class SomeClass(object):

    cvar = 'I am a class variable'

    def __init__(self):
        self.ivar = 'I am an instance variable'

4

文档

https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#info-field-lists 截至 Sphinx==6.1.3 目前表示它们都完全相同,这很遗憾:

在当前版本中,所有 var、ivar 和 cvar 都被表示为“变量”。没有任何区别。

:ivar: vs :cvar 最小可运行示例

以下是一个最小可运行示例,显示它们可能被设计为如何使用以及输出的样子。截至 Sphinx==6.1.3,它们没有渲染差异,因此对于源读取器来说只是语义上的问题,但无论如何也值得做。

因为我不确定何时使用,所以不显示:var:!也许模块级变量是最好的选择?如何在Python中记录模块常量?但它在模块docstring中不起作用。

main.py

class MyOtherClass:
    """
    This class does that.
    """
    pass

class MyClass:
    """
    Description for class.

    :ivar var1: Doc for var1
    :ivar var2: Doc for var2.
      Another line!
    :cvar class_var: Syntax also works for class variables.
    """

    class_var: int

    def __init__(self, par1: int, par2: MyOtherClass):
        self.var1: int = par1

        self.var2: MyOtherClass = par2

    def method(self):
        """
        My favorite method.
        """
        pass

    @classmethod
    def cmethod():
        """
        My favorite class method.
        """
        pass

build.sh

sphinx-build . out

conf.py

import os
import sys
sys.path.insert(0, os.path.abspath('.'))
extensions = [ 'sphinx.ext.autodoc' ]
autodoc_default_options = {
    'members': True,
}
autodoc_typehints = "description"

index.rst

.. automodule:: main

requirements.txt

Sphinx==6.1.3

在执行./build.sh之后,out/index.html下的输出如下所示: enter image description here

#: 文档注释

这是另一种记录实例和类变量的方法。

目前两种方法之间存在权衡,遗憾的是没有一种明显优越的方法。

缺点:

  • "Variables:"分组看起来更整洁,TODO链接到功能请求

优点:

  • 您不必多次输入属性名称
  • 显示类型

两者都可以更好:

  • 清楚地显示class_var是类变量?TODO链接到功能请求

除了self.var1 = par1 # Doc for var1语法外,您还可以:

main.py

class MyClass:
    """
    Description for class.
    """

    #: Syntax also works for class variables.
    class_var: int = 1

    def __init__(self, par1: int, par2: MyOtherClass):
        #: Doc for var1
        self.var1: int = par1

        #: Doc for var2.
        #: Another line!
        self.var2: MyOtherClass = par2

    def method(self):
        """
        My favorite method.
        """
        pass

    @classmethod
    def cmethod():
        """
        My favorite class method.
        """
        pass

产生:

enter image description here

#: 语法的文档位于:https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#directive-autoproperty

在 Python 3.10 和 Ubuntu 22.10 上进行了测试。


1
你的示例之所以有效,是因为你的变量名按照所需的词汇顺序排序。如果你将 "class_var" 重命名为 "the_class_var",它将出现在 "method()" 之后。 - Dr. Volker Jaenisch
@Dr.VolkerJaenisch,同样在#: 中,非类变量var1var2也遇到了同样的问题。我认为这个#: 输出方面比较劣(没有“变量”分组),与:ivar:相比唯一的缺点就是这个,真是遗憾。 - Ciro Santilli OurBigBook.com

0
也许不必担心这些特定标签之间的区别,如果需要使用变量,请坚持使用“var”,因为文档表明:
还有许多其他信息字段,但它们可能是冗余的: ...(包括)... var,ivar,cvar:变量的描述。 ...
请参见:

http://thomas-cokelaer.info/tutorials/sphinx/docstring_python.html


4
有许多其他的信息字段,但它们可能是多余的。关于它们是否多余,我希望这份文件能更加具体一些。虽然这种情况很可能存在,但我几乎不相信它,因为它听起来不合理。我们还有哪些线索可以验证这一点? - Rusty Weber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接