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.stats.distributions
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 子模块。