一般惯例

有许多方法可以帮助Sage,包括共享脚本和Sage工作表,这些工作表使用Sage实现新功能,改进Sage库,或者使用Sage分发的许多底层库 1. 本指南的重点是编辑Sage库本身。

Sage不仅仅是将功能集合在一起。它是关于提供一个清晰、系统和一致的方法来访问大量的算法,在一个在数学上有意义的连贯的框架中。在Sage的设计中,对象的语义、定义等都是通过在日常数学中如何使用相应的对象来实现的。

1

看到了吗https://www.sagemath.org/links-components.html每一份Sage的完整包装清单

为了实现使Sage易于阅读、维护和改进的目标,Sage包含的所有Python/Cython代码都应该遵循本章讨论的样式约定。

Python代码样式

为Sage编写代码时,请遵循标准的Python格式规则,如下网址所述:

特别地,

  • 缩进级别使用4个空格。不要使用制表符,因为它们会导致缩进混乱。大多数编辑器都有一个功能,当按下tab键时,将插入4个空格。此外,许多编辑器会自动搜索/替换前导标签,用4个空格。

  • 赋值前后的空白以及表达式中优先级最低的二元运算符:

    i = i + 1
    c = (a+b) * (a-b)
    
  • 前后没有空格 = 如果用于关键字参数,则进行签名:

    def complex(real, imag=0.0):
        return magic(r=real, i=imag)
    
  • 括号、方括号和大括号内没有空格:

    spam(ham[1], {eggs: 2})
    [i^2 for i in range(3)]
    
  • 使用所有小写函数名,并用下划线分隔单词。例如,我们鼓励您使用命名约定编写Python函数:

    def set_some_value():
        return 1
    

    但是,请注意,有些函数在有意义的地方确实有大写字母。例如,LLL算法的格约简函数被称为 Matrix_integer_dense.LLL .

  • 对类名使用CamelCase::

    class SomeValue(object):
        def __init__(self, x):
        self._x  = 1
    

    以及模拟对象构造函数的工厂函数 PolynomialRing 或:

    def SomeIdentityValue(x):
        return SomeValue(1)
    

文件和目录结构

大致来说,Sage目录树的布局是这样的。请注意,我们使用 SAGE_ROOT 作为包含Sage源的目录的(任意)名称的快捷方式:

SAGE_ROOT/
    sage          # the Sage launcher
    Makefile      # top level Makefile
    build/        # Sage's build system
        deps
        install
        ...
        pkgs/     # install, patch, and metadata from spkgs
    src/
        setup.py
        module_list.py
        ...
        sage/            # Sage library
            ext_data/    # extra Sage resources (formerly src/ext)
        mac-app/         # would no longer have to awkwardly be in extcode
        bin/             # the scripts in local/bin that are tracked
    upstream/            # tarballs of upstream sources
    local/               # installed binaries

pythonsage库代码 src/ 并使用以下约定。目录名可以是复数(例如。 rings )文件名几乎总是单数的(例如。 polynomial_ring.py ). 注意文件 polynomial_ring.py 可能仍然包含几种不同类型的多项式环的定义。

注解

我们鼓励您在文件包中包含各种注释、电子邮件、设计讨论等。生成这些纯文本文件(扩展名为 .txt )在一个名为 notes .

如果要在Sage库中创建新目录 SAGE_ROOT/src/sage (说, measure_theory ),该目录应包含一个文件 __init__.py 包含单行的 import all 除了你想添加的任何文件(比如, borel_measure.pybanach_tarski.py ),以及一个文件 all.py 列出从该目录中导入的内容,这些内容非常重要,足以在启动时位于Sage的全局命名空间中。文件 all.py 可能看起来像这样:

from borel_measure import BorelMeasure
from banach_tarski import BanachTarskiParadox

但通常最好使用lazy import框架:

from sage.misc.lazy_import import lazy_import
lazy_import('sage.measure_theory.borel_measue', 'BorelMeasure')
lazy_import('sage.measure_theory.banach_tarski', 'BanachTarskiParadox')

然后在文件里 SAGE_ROOT/src/sage/all.py ,添加一行:

from sage.measure_theory.all import *

非pythonsage源代码和支持文件应该放在 SAGE_ROOT/src/sage/ext_data/ . 然后,它们将自动复制到 SAGE_ROOT/local/share/sage/ext/ 在构建过程中,并且可以在运行时使用 SAGE_EXTCODE . 例如,如果 file 放置在 SAGE_ROOT/src/sage/ext_data/directory/ 可以通过以下方式访问:

from sage.env import SAGE_EXTCODE
file = os.path.join(SAGE_EXTCODE, 'directory', 'file')

SAGE_EXTCODE 因为不是所有的分发都有 SAGE_ROOT .

通过复制/粘贴学习

对于这里讨论的所有约定,您可以在Sage库中找到许多示例。浏览代码是有帮助的,但是搜索也是有帮助的:函数 search_srcsearch_defsearch_doc 值得了解。简而言之,从“Sage”的提示, search_src(string) 在Sage库代码中搜索字符串 string . 命令 search_def(string) 执行类似的搜索,但仅限于函数定义,而 search_doc(string) 搜索Sage文档。有关更多信息,请参见doc字符串和选项。

Sage库代码文件的标题

每个Sage文件的格式如下:

r"""
<Short one-line summary that ends with no period>

<Paragraph description>

EXAMPLES::

<Lots and lots of examples>

AUTHORS:

- YOUR NAME (2005-01-03): initial version

- person (date in ISO year-month-day format): short desc

"""

# ****************************************************************************
#       Copyright (C) 2013 YOUR NAME <your email>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#                  https://www.gnu.org/licenses/
# ****************************************************************************

例如,请参见 SAGE_ROOT/src/sage/rings/integer.pyx ,其中包含的实现 ZZ . 对该文件作出重大贡献的人员的姓名出现在 AUTHORS 第节。如果你是别人的话,你可以把你的名字加在名单上,但不要在描述中过于冗长。这个 AUTHORS 部分显示了历史的粗略概述,特别是如果很多人都在处理这个源文件的话。关于谁编写了git存储库的权威日志(请参见 git blame

Sage附带的所有代码都必须在GPLv2+或兼容的(即限制较少的许可证)下获得许可证(例如BSD许可证)。

文档字符串

函数的docstring:content

每个 函数必须具有包含以下信息的docstring。您可以使用Sage的现有功能作为模板。

  • A one-sentence description 函数的。

    它后面必须有一个空行,并以句点结尾。它将函数或方法的效果描述为命令(“Do this”,“Return that”),而不是“Return the pathname…”之类的描述。

    对于类的方法,建议参考 self 以描述性的方式论证,除非这会导致混淆。例如,如果 self 是一个整数 this integerthe integer 更具描述性,最好写下来

    Return whether this integer is prime.
    
  • A 更详细的描述 .

    如果一句话的描述不需要更多的解释,这是可选的。

    从假设对象开始,如果有的话。例如,

    The poset is expected to be ranked.
    

    如果函数在非排名偏序集上调用时引发异常。

    定义你的术语

    The lexicographic product of `G` and `H` is the graph with vertex set ...
    

    并提到可能的别名

    The tensor product is also known as the categorical product and ...
    
  • INPUT 和一个 OUTPUT 描述函数的输入/输出的块。

    输入块描述函数接受的所有参数。

    1. 类型名应该是描述性的,但不必代表Sage/Python类型。例如,使用“integer”表示任何类似于整数的行为,而不是 int .

    2. 如果适用,请提及输入参数的默认值。

    INPUT:
    
    - ``n`` -- integer
    
    - ``p`` -- prime integer (default: `2`); coprime with ``n``
    

    输出块描述预期输出。如果函数的一句话描述需要更多解释,则需要这样做。

    OUTPUT: the plaintext decrypted from the ciphertext ``C``
    

    通常情况下,输出由几个项目组成。

    OUTPUT: a tuple of
    
    - the reduced echelon form `H` of the matrix `A`
    
    - the transformation matrix `U` such that `UA = H`
    

    建议您对复杂的输出足够详细。

    OUTPUT:
    
    The decomposition of the free module on which this matrix `A` acts from
    the right (i.e., the action is `x` goes to `xA`), along with whether
    this matrix acts irreducibly on each factor. The factors are guaranteed
    to be sorted in the same way as the corresponding factors of the
    characteristic polynomial.
    
  • EXAMPLES 块作为例子。这不是可选的。

    这些示例用于文档,但它们也像测试块一样在每次发布之前进行测试。

    他们应该对所讨论的功能有很好的覆盖。

  • A SEEALSO 块(强烈推荐)与Sage相关部分的链接。这有助于用户找到他们感兴趣的特性并发现新特性。

    .. SEEALSO::
    
        :ref:`chapter-sage_manuals_links`,
        :meth:`sage.somewhere.other_useful_method`,
        :mod:`sage.some.related.module`.
    

    超链接 有关如何在Sage中设置链接的详细信息。

  • ALGORITHM 块(可选)。

    它指出使用了什么算法和/或软件,例如。 ALGORITHM: Uses Pari . 下面是一个较长的示例,并附有参考书目:

    ALGORITHM:
    
    The following algorithm is adapted from page 89 of [Nat2000]_.
    
    Let `p` be an odd (positive) prime and let `g` be a generator
    modulo `p`. Then `g^k` is a generator modulo `p` if and only if
    `\gcd(k, p-1) = 1`. Since `p` is an odd prime and positive, then
    `p - 1` is even so that any even integer between 1 and `p - 1`,
    inclusive, is not relatively prime to `p - 1`. We have now
    narrowed our search to all odd integers `k` between 1 and `p - 1`,
    inclusive.
    
    So now start with a generator `g` modulo an odd (positive) prime
    `p`. For any odd integer `k` between 1 and `p - 1`, inclusive,
    `g^k` is a generator modulo `p` if and only if `\gcd(k, p-1) = 1`.
    

    参考书目应该放在Sage的主要书目文件中, SAGE_ROOT/src/doc/en/reference/references/index.rst

    .. [Nat2000] \M. B. Nathanson. Elementary Methods in Number Theory.
       Springer, 2000.
    
  • A NOTE 提示/技巧块(可选)。

    .. NOTE::
    
        You should note that this sentence is indented at least 4
        spaces. Never use the tab character.
    
  • A WARNING 阻止获取有关代码的关键信息(可选)。

    例如,代码中断的已知情况,或者用户应该知道的任何情况。

    .. WARNING::
    
        Whenever you edit the Sage documentation, make sure that
        the edited version still builds. That is, you need to ensure
        that you can still build the HTML and PDF versions of the
        updated documentation. If the edited documentation fails to
        build, it is very likely that you would be requested to
        change your patch.
    
  • A TODO 阻止未来改进(可选)。

    它可以包含禁用的doctest来演示所需的功能。下面是一个TODO块的示例:

    .. TODO::
    
        Add to ``have_fresh_beers`` an interface with the faster
        algorithm "Buy a Better Fridge" (BaBF)::
    
            sage: have_fresh_beers('Bière de l\'Yvette', algorithm="BaBF") # not implemented
            Enjoy !
    
  • A PLOT 块,用图片说明函数的输出。

    用Sage代码生成对象 g 用一个 .plot 方法,然后调用 sphinx_plot(g)

    .. PLOT::
    
        g = graphs.PetersenGraph()
        sphinx_plot(g)
    
  • A REFERENCES 阻止列出相关书籍或论文(可选)。

    几乎所有的书目信息都应该放在主书目文件中,见下文。引文将链接到主书目,读者可以在那里找到书目的详细信息(引文语法见下文)。因此,通常不需要单个docstring中的引用块。

    然而,如果有相关的源没有在docstring中显式地提到,或者如果docstring特别长,则引用块是有用的。在这种情况下,将书目信息添加到主书目文件中(如果尚未存在),并将参考块添加到docstring中,如下所示:

    REFERENCES:
    
    For more information, see [Str1969]_, or one of the following references:
    
    - [Sto2000]_
    
    - [Voe2003]_
    

    注意后面的下划线使引文变成了超链接。有关主书目文件的更多信息,请参见下文。有关引文的更多信息,请参阅 Sphinx/reST markup for citations . 有关trac票证或wikipedia的链接,请参阅 超链接 .

  • A TESTS 块(强烈推荐)。

    格式与示例类似,包含与用户无关的测试。特别是,当用户通过 foo? :它们被函数剥离 sage.misc.sagedoc.skip_TESTS_block() .

    特殊情况和角落情况,如数字0,一个元素组等,通常应该到这个块。这也是大多数输入验证测试的正确位置;例如,如果函数接受 direction='up'direction='down' ,您可以使用此块来检查 direction='junk' 引发异常。

    出于删除的目的,“TESTS”块是一个以“TEST:”或“TESTS:”(或用两个冒号相同)开头的块,位于一行上,以缩进量小于“TESTS”的行结尾,或者以具有相同缩进级别(不超过)的行结束,与以下内容之一匹配:

    • 狮身人面像的指令。。foo:”,可选择后跟其他文本。

    • 格式为“大写:”的文本,可选择后跟其他文本。

    • 看起来像reST头的行:一行包含任何内容,后跟只包含空白的行,后跟一系列连字符、等号或其他字符,这些字符是reST头的有效标记: - = ` : ' " ~ _ ^ * + # < > . 但是,行只包含双冒号 :: 不要结束“测试”块。

关于Sphinx指令与其他块的说明

Sage中使用的主要斯芬克斯指令是:

.. MATH::.. NOTE::.. PLOT::.. RUBRIC::.. SEEALSO::.. TODO::.. TOPIC::.. WARNING:: .

它们必须和上面写的一模一样,例如 WARNING::.. WARNING :: 不会起作用。

也有一些其他指令,但使用频率较低,即:

.. MODULEAUTHOR::.. automethod::.. autofunction::.. image::.. figure:: .

其他块不能用作指令;例如 .. ALGORITHM:: 根本不会显示。

Sage文档样式

所有Sage文档都是用restructedText(reST)编写的,并由Sphinx处理。看到了吗http://www.sphinx-doc.org/rest.html作为介绍。Sage强加了这些风格:

  • 行数应少于80个字符。如有疑问,请阅读 PEP8: Maximum Line Length .

  • 所有reST和Sphinx指令(比如 .. WARNING::.. NOTE::.. MATH:: 等等)都是大写的。

  • 代码片段用双反撇号引用。这包括函数参数和Python文本,比如 ``True '' ``False ````None ``. 例如:

    If ``check`` is ``True``, then ...
    

Sage的主人 BIBLIOGRAPHY 文件

所有参考书目应保存在主书目文件中, SAGE_ROOT/src/doc/en/reference/references/index.rst 格式为

.. [Gau1801] \C. F. Gauss, *Disquisitiones Arithmeticae*, 1801.

.. [RSA1978] \R. Rivest, A. Shamir, L. Adleman,
             "A Method for Obtaining Digital Signatures and
             Public-Key Cryptosystems".
             Communications of the ACM **21** (February 1978),
             120–126. :doi:`10.1145/359340.359342`.

括号中的部分是引文索引键:给定这些示例,您可以使用 [Gau1801]_ 在docstring中提供指向第一个引用的链接。注意后面的下划线使引文成为超链接。

如果可能的话,钥匙应该有这样的格式:对于一个作者,使用姓氏的前三个字母,然后是年份;对于多个作者,使用每个姓氏的第一个字母,然后是年份。请注意,年份应该是四位数,而不仅仅是最后两位数——例如,Sage已经有了1910年和2010年的参考文献。

在书目列表中缩写作者的名字时,一定要在其前面加一个反斜杠。这样可以确保 (C. 在上面的示例中)将不会被解释为列表枚举器。

有关引文的更多信息,请参阅 Sphinx/reST markup for citations .

模板

记录函数时使用以下模板。注意缩进:

def point(self, x=1, y=2):
    r"""
    Return the point `(x^5,y)`.

    INPUT:

    - ``x`` -- integer (default: `1`); the description of the
      argument ``x`` goes here. If it contains multiple lines, all
      the lines after the first need to begin at the same indentation
      as the backtick.

    - ``y`` -- integer (default: `2`); the description of the
      argument ``y``

    OUTPUT: the point as a tuple

    EXAMPLES:

    This example illustrates ... ::

        sage: A = ModuliSpace()
        sage: A.point(2,3)
        xxx

    We now ... ::

        sage: B = A.point(5,6)
        sage: xxx

    It is an error to ... ::

        sage: C = A.point('x',7)
        Traceback (most recent call last):
        ...
        TypeError: unable to convert 'r' to an integer

    .. NOTE::

        This function uses the algorithm of [BCDT2001]_ to determine
        whether an elliptic curve `E` over `Q` is modular.

    ...

    .. SEEALSO::

        :func:`line`

    TESTS::

        sage: A.point(42, 0)  # Check for corner case y=0
        xxx
    """
    <body of the function>

主书目文件将包含

.. [BCDT2001] Breuil, Conrad, Diamond, Taylor,
              "Modularity ...."

强烈建议您:

  • 使用 Latex 排版(请参见 Latex 排版

  • 自由地描述例子的作用。

    注解

    在示例代码之后和下一个示例的解释文本之前必须有一个空白行(缩进是不够的)。

  • 用示例说明函数引发的异常(如上所述:“It is a error to [..] ", ...)

  • 包括许多例子。

    它们对用户有帮助,对Sage的质量和适应性至关重要。如果没有这样的例子,对Sage的某个部分进行的一些小的改动会破坏其他东西,直到后来有人使用该系统时才会被发现,这是不可接受的。

私人功能

名称以下划线开头的函数被视为私有函数。它们不会出现在参考手册中,它们的docstring不应该包含任何对Sage用户至关重要的信息。您可以使它们的docstring成为另一个方法文档的一部分。例如::

class Foo(SageObject):

    def f(self):
        """
        <usual docstring>

        .. automethod:: _f
        """
        return self._f()

    def _f(self):
         """
         This would be hidden without the ``.. automethod::``
         """

私有函数应该包含一个示例(或测试)块。

一个特殊情况是构造函数 __init__ :由于其特殊地位 __init__ 如果还没有docstring类,则使用docstring作为类。也就是说,您可以执行以下操作:

sage: class Foo(SageObject):
....:     # no class docstring
....:     def __init__(self):
....:         """Construct a Foo."""
sage: foo = Foo()
sage: from sage.misc.sageinspect import sage_getdoc
sage: sage_getdoc(foo)              # class docstring
'Construct a Foo.\n'
sage: sage_getdoc(foo.__init__)     # constructor docstring
'Construct a Foo.\n'

Latex 排版

在Sage的文档中,允许使用 Latex 代码,并用 反勾或美元符号

`x^2 + y^2 = 1 ‘和 $x^2 + y^2 = 1$ 两者都有收益 x^2 + y^2 = 1 .

反斜杠: 对于包含反斜杠的LaTeX命令,请使用双反斜杠或以 r""" 而不是 """ . 以下两项均有效:

def cos(x):
    """
    Return `\\cos(x)`.
    """

def sin(x):
    r"""
    Return $\sin(x)$.
    """

数学块: 这与LaTeX语法类似 \[<math expression>\] (或) $$<math expression>$$ ). 例如:

.. MATH::

    \sum_{i=1}^{\infty} (a_1 a_2 \cdots a_i)^{1/i}
    \leq
    e \sum_{i=1}^{\infty} a_i
\[sum{i=1}^{infty}(a_1 a_2cdots a_i)^{1/i}leq esum{i=1}^{infty}a_i\]

这个 对齐的 环境就像 Latex 一样工作:

.. MATH::

    \begin{aligned}
     f(x) & = x^2 - 1 \\
     g(x) & = x^x - f(x - 2)
    \end{aligned}
\[开始{aligned}f(x)&=x^2-1\g(x)&=x^x-f(x-2)end{aligned}\]

在构建PDF文档时,所有内容都会转换为LaTeX,并且每个数学块都会自动包装在一个数学环境中—尤其是,它被转换为 \begin{{gather}} block \end{{gather}} . 所以如果你想使用 Latex 环境(比如 align )在普通 Latex 中是不会这样包装的,你必须加一个 :无标记: 标记为数学模式。另请参见 Sphinx's documentation for math blocks . :

.. MATH::
   :nowrap:

   \begin{align}
      1+...+n &= n(n+1)/2\\
      &= O(n^2)\\
   \end{align}
开始{align}1+…+n&=n(n+1)/2\&=O(n^2)\end{align}

可读性平衡: 在交互控制台中,文档中包含的LaTeX公式由它们的LaTeX代码表示(去掉反斜杠)。在这种情况下 \\frac{{a}}{{b}} 可读性不如 a/ba b^{{-1}} (有些用户甚至不知道LaTeX代码)。尽你所能让每个人都感到愉快。

公环 (Bold{{Z}},Bold{{N}},...) :Sage-LaTeX样式是使用本地定义的宏对标准环和字段进行排版 \\Bold (例如) \\Bold{{Z}} 给予 Bold{{Z}}

Shortcuts are available which preserve readability, e.g. \\ZZ (ZZ), \\RR (RR), \\CC (CC), and \\QQ (QQ). They appear as LaTeX-formatted \\Bold{Z} in the html manual, and as Z in the interactive help. Other examples: \\GF{q} (GF{q}) and \\Zmod{p} (Zmod{p}).

查看文件 SAGE_ROOT/src/sage/misc/latex_macros.py 以获取完整列表和有关如何添加更多宏的详细信息。

编写可测试的示例

Sage文件中的示例有双重目的:

  • 它们提供 插图 代码对用户的使用

  • 他们是 测验 在每次发布之前都要检查,以帮助我们避免新的错误。

所有添加到Sage中的新医生都应该 通过所有测试 (见 运行Sage的博士学位 ),即跑步 sage -t your_file.py 不应给出任何错误消息。以下是关于如何撰写博士论文的说明。

医生应该测试什么:

  • 有趣的例子 函数能做什么。这将是最有助于失去用户。这也是检查著名定理的机会(以防万一):

    sage: is_prime(6) # 6 is not prime
    False
    sage: 2 * 3 # and here is a proof
    6
    
  • 所有 有意义的组合 输入参数。例如,函数可以接受 algorithm="B" 论证和医生都应该包括这两个方面 algorithm="A"algorithm="B" .

  • 角盒: 代码应该能够处理0输入、空集、空矩阵、空函数。。。所有角落的箱子都应该检查,因为它们是最有可能被打破,现在或将来。这可能属于测试块(请参见 函数的docstring:content

  • 系统测试 所有小尺寸的输入,或 随机的 如果可能的话。

    注解

    注意 TestSuites 是在特定情况下自动生成某些测试的方法。看到了吗 SAGE_ROOT/src/sage/misc/sage_unittest.py .

语法:

  • 环境: 如果您在Sage的交互式控制台中复制/粘贴doctest,它们应该可以工作。例如,函数 AA() 在文件中 SAGE_ROOT/src/sage/algebras/steenrod/steenrod_algebra.py 包括包含以下内容的示例块:

    sage: from sage.algebras.steenrod.steenrod_algebra import AA as A
    sage: A()
    mod 2 Steenrod algebra, milnor basis
    

    Sage不知道这个功能 AA() 默认情况下,因此需要在测试之前导入它。因此示例中的第一行。

  • 准备: 就像在Sage的控制台里, 4/3 收益率 4/3 而不是 1 与Python2.7一样。测试是在标准的Sage shell环境中对输入进行完整的Sage准备,如中所述 Sage准备 .

  • 正在写入文件: 如果测试输出到文件,则该文件应为临时文件。使用 tmp_filename() 获取临时文件名,或 tmp_dir() 获取临时目录。一个来自 SAGE_ROOT/src/sage/plot/graphics.py ):

    sage: plot(x^2 - 5, (x, 0, 5), ymin=0).save(tmp_filename(ext='.png'))
    
  • 多行文档: 可以使用行延续标记编写跨越多行的测试 ....: ::

    sage: for n in srange(1,10):
    ....:     if n.is_prime():
    ....:         print(n)
    2
    3
    5
    7
    
  • ** Python 3印花:** 即使Python2的print语法目前仍然可以在您自己的代码中使用,Python3的print语法必须在Sage代码和doctests中使用。如果你在博士论文中使用老式印刷体,它会引起语法错误:

    sage: print "not like that"
    Traceback (most recent call last):
    ...
    SyntaxError: ...
    sage: print("but like this")
    but like this
    
  • 拆分长线: 您可能需要用反斜杠拆分长代码行。注意:此语法是非标准的,将来可能会删除:

    sage: n = 123456789123456789123456789\
    ....:     123456789123456789123456789
    sage: n.is_prime()
    False
    
  • Doctests标志: 可以使用标志来更改doctest的行为:请参阅 影响医生的特殊标记 .

影响医生的特殊标记

示例代码中过于复杂的输出可以通过省略号来缩短 ... ::

sage: [ZZ(n).ordinal_str() for n in range(25)]
['0th',
 '1st',
 '2nd',
 '3rd',
 '4th',
 '5th',
 ...
 '21st',
 '22nd',
 '23rd',
 '24th']
sage: ZZ('sage')
Traceback (most recent call last):
...
TypeError: unable to convert 'sage' to an integer

有关省略号标记的正确用法,请参阅 :python:`Python's documentation <library/doctest.html#doctest.ELLIPSIS>` .

您可以在示例代码中添加一些神奇的注释,这些注释可以更改Sage doctest框架验证输出的方式。以下是一份综合清单:

  • 随机: 将执行该行,但不会使用文档字符串中的输出检查其输出:

    sage: c = CombinatorialObject([1,2,3])
    sage: hash(c)  # random
    1335416675971793195
    sage: hash(c)  # random
    This doctest passes too, as the output is not checked
    

    但是,大多数生成伪随机输出的函数不需要这个标记,因为doctesting框架保证Sage中用于给定doctest的伪随机数生成器(prng)的状态。

    在可能的情况下,避免这个问题,例如:与其在doctest中检查hash的值,不如说明如何成功地将其用作dict中的键。

  • 长时间: 只有在 --long 提供选项,例如。 sage -t --long f.py .

    对于运行时间超过一秒钟的医生测试,请使用它。任何例子都不应超过30秒:

    sage: E = EllipticCurve([0, 0, 1, -1, 0])
    sage: E.regulator()        # long time (1 second)
    0.0511114082399688
    
  • tol公差: 行返回的数值只验证给定公差。当输出因系统相关(浮点运算、数学库等)或非确定性算法而受到数值噪声的影响时,它非常有用。

    • 前缀可以是 abs[olute]rel[ative] 指定是否测量 绝对的相对的 错误(请参阅 :wikipedia:`Approximation_error`

    • 如果没有 abs/rel 则错误被认为是 absolute 当期望值为 zerorelative 对于 非零 价值观。

    sage: n(pi)  # abs tol 1e-9
    3.14159265358979
    sage: n(pi)  # rel tol 2
    6
    sage: n(pi)  # abs tol 1.41593
    2
    sage: K.<zeta8> = CyclotomicField(8)
    sage: N(zeta8)  # absolute tolerance 1e-10
    0.7071067812 + 0.7071067812*I
    

    多个数值: 复数、矩阵或多项式的表示通常涉及几个数值。如果带公差的doctest包含多个数字,则分别检查每个数字:

    sage: print("The sum of 1 and 1 equals 5")  # abs tol 1
    The sum of 2 and 2 equals 4
    sage: e^(i*pi/4).n() # rel tol 1e-1
    0.7 + 0.7*I
    sage: ((x+1.001)^4).expand() # rel tol 2
    x^4 + 4*x^3 + 6*x^2 + 4*x + 1
    sage: M = matrix.identity(3) + random_matrix(RR,3,3)/10^3
    sage: M^2 # abs tol 1e-2
    [1 0 0]
    [0 1 0]
    [0 0 1]
    

    doctesting框架在错误计算中涉及的值由正则表达式定义 float_regex 在里面 sage.doctest.parsing .

  • 未实施未测试: 这条线从来没有试过。

    在非常长的文档测试中使用它,而这些文档只是文档。它还可以用来记录最终将要实现的内容:

    sage: factor(x*y - x*z)    # todo: not implemented
    

    用户还可以立即清楚地看到,所示示例当前不起作用。

    注解

    跳过文件/目录的所有doctest

    • 文件: 如果文件的前10行中有一行以 r""" nodoctest (或) """ nodoctest# nodoctest% nodoctest.. nodoctest ,或任何具有不同间距的文件),则将跳过该文件。

    • 目录: 如果目录包含文件 nodoctest.py ,则整个目录将被跳过。

    这两种方法都不适用于显式地作为命令行参数给定的文件或目录:它们总是经过测试的。

  • py2py3: 在python2上运行该行 only 或Python 3 only 分别。一般来说,这是应该避免的,因为代码应该同时在python2和python3上测试,但是有时也有一些测试不适用于其中一个,比如依赖于可选特性的测试,而这些特性只在Python的一个或另一个版本上可用。

  • 可选: 一条标有 optional - keyword 除非 --optional=keyword 标志传递给 sage -t (见 运行可选的doctest ). 主要应用包括:

    • 可选软件包: 当一条生产线需要安装可选包时(例如 sloane_database 包装)::

      sage: SloaneEncyclopedia[60843]    # optional - sloane_database
      
    • 互联网: 对于需要internet连接的线路:

      sage: oeis(60843)                 # optional - internet
      A060843: Busy Beaver problem: a(n) = maximal number of steps that an
      n-state Turing machine can make on an initially blank tape before
      eventually halting.
      
    • bug: 对于描述错误的行。或者,使用 # known bug 相反:它是 optional bug .

      The following should yield 4.  See :trac:`2`. ::
      
          sage: 2+2  # optional: bug
          5
          sage: 2+2  # known bug
          5
      

    注解

    • 后面还有话吗 # optional 被解释为包名称的列表,用空格分隔。

    • 第一个单词后面的任何标点符号(句点、逗号、连字符、分号等等)都将结束包列表。单词之间有连字符或冒号 optional 第一个包名是允许的。因此,你不应该写作 optional: needs package CHomP 但是很简单 optional: CHomP .

    • 可选标记不区分大小写,因此您也可以编写 optional: chOMP .

  • 间接试验: 在函数的docstring中 A(...) ,一个电话 A 其中的名字 A 不应出现此标志。这样可以防止 sage --coverage <file> 将docstring报告为“不测试应该测试的内容”。

    在测试诸如 __repr____add__ ,等等。在通过调用测试函数时也使用它 B 内部调用 A

    This is the docstring of an ``__add__`` method. The following
    example tests it, but ``__add__`` is not written anywhere::
    
        sage: 1+1 # indirect doctest
        2
    
  • 32-bit64-bit: 对于在32位或64位计算机上表现不同的测试。请注意,此特定标志将应用于 输出 行,而不是输入行:

    sage: hash(2^31 + 2^13)   # py3
    8193                      # 32-bit
    2147491840                # 64-bit
    sage: hash(2^31 + 2^13)   # py2
    -2147475456               # 32-bit
    2147491840                # 64-bit
    

使用 search_src 从Sage提示符(或 grep ),可以很容易地找到上述关键词。在下列情况下 todo: not implemented 我们可以利用这样的搜索结果来指导Sage的进一步发展。

运行自动文档测试

本节介绍Sage对以下类型的测试文件的自动测试: .py.pyx.sage.rst . 简而言之,使用 sage -t <file> 来测试 <file> 言行一致。有关更多详细信息,请参见以下小节。另请参见 文档字符串 讨论如何在文档字符串中包含示例以及遵循什么约定。本章 运行Sage的博士学位 包含有关Sage库中doctesting模块的教程。

测试.py、.pyx和.sage文件

sage -t <filename.py> 测试中的所有代码示例 filename.py . 类似的备注适用于 .sage.pyx 文件夹:

$ sage -t [--verbose] [--optional]  [files and directories ... ]

Sage doctesting框架基于标准Python doctest模块,但具有许多附加特性(例如并行测试、超时、可选测试)。Sage博士认识到 sage: 提示以及 >>> 提示。它还为医生做准备,就像在交互式的Sage会议中一样。

如果文件中的代码在 sage: 没有额外的导入提示。因此,用户可以保证准确地从您为文档编写的示例中复制代码,并让它们正常工作。

有关详细信息,请参阅 运行Sage的博士学位 .

测试reST文档

sage -t <filename.rst> 在reST文档的逐字环境中测试示例。

当然,在reST文件中,常常在不同的逐字环境之间插入解释性文本。要将逐字环境链接在一起,请使用 .. link 评论。例如:

EXAMPLES::

        sage: a = 1


Next we add 1 to ``a``.

.. link::

        sage: 1 + a
        2

如果要将所有逐字环境链接在一起,可以将 .. linkall 文件中的任何位置,单独一行。(为了清楚起见,最好把它放在文件的顶部。) sage -t 就好像有一个 .. link 在每个逐字环境之前。文件 SAGE_ROOT/src/doc/en/tutorial/interfaces.rst 包含一个 .. linkall 例如指令。

你也可以把 .. skip 在测试文件时跳过该示例。这个和 .. link 在前面的示例中。

查看中的文件 SAGE_ROOT/src/doc/en/tutorial/ 关于如何在Sage的reST文档中包含自动测试的许多示例。

关于空白的一般编码样式

缩进使用空格而不是制表符。maketabs与maketabs的语法意义不同。

不要添加尾随空格。

Sage使用文件为Emacs提供编辑器配置 .dir-locals.el ,使用空格代替制表符。关于尾随空格,请参见https://www.emacswiki.org/emacs/DeletingWhitespace各种解决方案。

如果您使用另一个编辑器,我们建议您对其进行配置,这样就不会向文件添加选项卡。

全局选项

类的全局选项可以在Sage中使用 GlobalOptions .

杂事

有些决定是武断的,但共同的约定使生活更容易。

  • 标识符中的非ASCII名称:

    • 翻译 äöaeoe ,像 moebius_function 对于Möbius函数。

    • 翻译 áa ,像 lovasz_number 为洛瓦兹号码。

  • 常用函数关键字参数:

    这是许多函数和方法采用的一些关键字参数的列表。为了保持一致性,您应该使用下面列表中的关键字,其含义如下所述。不要使用具有相同含义的不同关键字(例如,不要使用 method 使用 algorithm 相反)。

    • algorithm ,字符串或 None 或选择不同的实现算法。使用 None 作为一个默认值,它选择一个合理的默认值,该值可能取决于已安装的可选软件包。

    • certificate ,一个布尔值 False 默认值:函数是否应连同结果一起返回某种证书。与 certificate=True 返回值应该是一对 (r, c) 在哪里? r 结果是 certificate=Falsec 是证书还是 None 如果没有有意义的完整证书。

    • proof ,一个布尔值 True 默认值:如果 True ,需要经过数学证明的计算。如果 False ,可以使用概率算法或依赖于RH等未证明假设的算法。

    • check ,布尔值:执行一些附加检查以验证输入参数。否则,这不应影响代码的功能:如果代码与 check=True ,它还应该与 check=False .

    • coerce ,布尔值:将输入参数转换为合适的父级。这通常在构造函数中使用。可以使用调用方法 coerce=False 如果父对象是正确的,则跳过一些检查。

    • inplace ,布尔值:是就地修改对象还是返回副本。