SciPy API#

从 SciPy 导入#

在 Python 中,库的公共 API 和私有实现细节之间的区别并不总是很明确。与 Java 等其他语言不同,在 Python 中可以访问“私有”函数或对象。有时这可能会很方便,但请注意,如果你这样做,你的代码可能会在将来发行版中毫无征兆地中断。一些广泛认同的 Python 中公开和非公开内容的规则是

  • 名称以以下划线开头的函数/方法/类和模块属性是私有的。

  • 如果类名称以以下划线开头,则无论是否以下划线开头,其成员都不是公开的。

  • 如果包中的模块名称以以下划线开头,则无论是否以下划线开头,其成员都不是公开的。

  • 如果模块或包定义了 __all__,则可靠地定义了公共界面。

  • 如果模块或包未定义 __all__,则所有名称不会以下划线开头都是公开的。

注意

阅读上述指南,可以得出结论,即每个私有模块或对象的开头都是下划线。事实并非如此;下划线的存在确实将某些内容标记为私有,但下划线的缺失并不意味着某些内容是公开的。

在 SciPy 中有一些模块的名称不以下划线开头,但应被视为私有的。为了阐明这些模块是什么,我们在下面定义 SciPy 的公共 API 是什么,并给出一些有关如何从 SciPy 导入模块/函数/对象的建议。

从 SciPy 导入函数的指南#

SciPy 子模块的命名空间中的所有内容都是公开的。一般来说,在 Python 中,建议使用命名空间。例如,该函数 curve_fit(已在 scipy/optimize/_minpack_py.py 中定义)应如下所示进行导入

import scipy
result = scipy.optimize.curve_fit(...)

或者也可以像这样将子模块作为命名空间使用

from scipy import optimize
result = optimize.curve_fit(...)

注意

对于 scipy.io,首选使用 import scipy,因为 io 也是 Python stdlib 中的一个模块的名称。

在某些情况下,公共 API 会更深一级。例如,scipy.sparse.linalg 模块是公开的,并且它所含的函数不可在 scipy.sparse 命名空间内获得。有时候,如果从更深一级导入函数,可能会使代码更易于理解。例如,在下面,如果选择第二种形式,那么很明显 lomax 就是一种分布

# first form
from scipy import stats
stats.lomax(...)

# second form
from scipy.stats import distributions
distributions.lomax(...)

在这种情况下,如果在下一部分记录了相关子模块是公开的,那么可以选择第二种形式。当然,您仍然可以使用

import scipy
scipy.stats.lomax(...)
# or
scipy.stats.distributions.lomax(...)

注意

SciPy 使用的是一种惰性加载机制,这意味着只有在您第一次尝试访问模块时,才会将它们加载到内存中。

API 定义#

下面列出的每个子模块都是公开的。这意味着这些子模块不太可能以不兼容的方式重命名或更改,且如果需要,在进行更改之前会为一个 SciPy 版本提出弃用警告。

SciPy 结构#

所有 SciPy 模块都应遵循以下惯例。在下面,SciPy 模块被定义为一个 Python 包,例如 yyy,位于 scipy/ 目录中。

  • 理想情况下,每个 SciPy 模块都应尽可能实现自包含。也就是说,它应对其他包或模块的依赖性降至最低。即使对其他 SciPy 模块的依赖性也应保持在最低水平。当然我们假设依赖 NumPy。

  • 目录 yyy/ 包含

    • 一个 meson.build 文件,其中包含子模块的构建配置。

    • 目录 tests/包含文件 test_<name>.py,对应于模块 yyy/<name>{.py,.so,/}

  • 私有模块应以下划线 _为前缀,例如 yyy/_somemodule.py

  • 用户可见函数应有良好的文档,遵循 NumPy 文档样式

  • 模块的 __init__.py 应在其文档字符串中包含主要参考文档。这通过 Sphinx 的自动模块指令连接到 doc/ 下的 Sphinx 文档。

    参考文档应首先使用 autosummary:: 指令对模块的内容进行分类列表,然后解释理解模块使用必不可少的要点。

    带有大量示例的教程式文档应单独存放并放在 doc/source/tutorial/ 下。

有关指导,请参见现有的 SciPy 子模块。