前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NumPy 1.26 中文文档(四十五)

NumPy 1.26 中文文档(四十五)

作者头像
ApacheCN_飞龙
发布2024-06-28 16:23:48
860
发布2024-06-28 16:23:48
举报
文章被收录于专栏:信数据得永生信数据得永生

原文:numpy.org/doc/

numpy.distutils.misc_util

原文:numpy.org/doc/1.26/reference/distutils/misc_util.html

代码语言:javascript
复制
numpy.distutils.misc_util.all_strings(lst)

如果 lst 中的所有项都是字符串对象,则返回 True。

代码语言:javascript
复制
numpy.distutils.misc_util.allpath(name)

将一个 / 分隔的路径名转换为使用 OS 路径分隔符的路径。

代码语言:javascript
复制
numpy.distutils.misc_util.appendpath(prefix, path)
代码语言:javascript
复制
numpy.distutils.misc_util.as_list(seq)
代码语言:javascript
复制
numpy.distutils.misc_util.blue_text(s)
代码语言:javascript
复制
numpy.distutils.misc_util.cyan_text(s)
代码语言:javascript
复制
numpy.distutils.misc_util.cyg2win32(path: str) → str

将路径从 Cygwin 本地转换为 Windows 本地。

使用 cygpath 实用程序(Base 安装的一部分)进行实际转换。如果失败,则回退返回原始路径。

处理默认的 /cygdrive 挂载前缀以及 /proc/cygdrive 便携前缀,自定义的 cygdrive 前缀如 //mnt,以及绝对路径如 /usr/src//home/username

参数:

pathstr

要转换的路径

返回:

converted_pathstr

转换后的路径

笔记

cygpath 实用程序文档:cygwin.com/cygwin-ug-net/cygpath.html 它包装的 C 函数文档:cygwin.com/cygwin-api/func-cygwin-conv-path.html

代码语言:javascript
复制
numpy.distutils.misc_util.default_config_dict(name=None, parent_name=None, local_path=None)

返回一个配置字典,用于配置文件 setup_.py 中定义的 configuration() 函数的使用。

代码语言:javascript
复制
numpy.distutils.misc_util.dict_append(d, **kws)
代码语言:javascript
复制
numpy.distutils.misc_util.dot_join(*args)
代码语言:javascript
复制
numpy.distutils.misc_util.exec_mod_from_location(modname, modfile)

使用 importlib 机制从文件 modfile 导入模块 modname。根据 spec.loader,模块可能未在 sys.modules 中注册。

代码语言:javascript
复制
numpy.distutils.misc_util.filter_sources(sources)

返回包含 C、C++、Fortran 和 Fortran 90 模块源文件名称的四个列表。

代码语言:javascript
复制
numpy.distutils.misc_util.generate_config_py(target)

生成包含在构建软件包过程中使用的 system_info 信息的 config.py 文件。

用法:

config[‘py_modules’].append((packagename, ‘config’,generate_config_py))

代码语言:javascript
复制
numpy.distutils.misc_util.get_build_architecture()
代码语言:javascript
复制
numpy.distutils.misc_util.get_cmd(cmdname, _cache={})
代码语言:javascript
复制
numpy.distutils.misc_util.get_data_files(data)
代码语言:javascript
复制
numpy.distutils.misc_util.get_dependencies(sources)
代码语言:javascript
复制
numpy.distutils.misc_util.get_ext_source_files(ext)
代码语言:javascript
复制
numpy.distutils.misc_util.get_frame(level=0)

从调用堆栈中返回给定级别的帧对象。

代码语言:javascript
复制
numpy.distutils.misc_util.get_info(pkgname, dirs=None)

为给定 C 库返回一个 info 字典。

info 字典包含了使用 C 库所需的选项。

参数:

pkgnamestr

包的名称(应与 .ini 文件的名称匹配,不带扩展名,例如,文件 foo.ini 对应的名称为 foo)。

dirssequence, optional

如果给定,应为额外目录序列,用于查找 npy-pkg-config 文件。在 NumPy 目录之前搜索这些目录。

返回:

infodict

具有构建信息的字典。

引发:

PkgNotFound

如果找不到包。

另请参阅

Configuration.add_npy_pkg_configConfiguration.add_installed_library

get_pkg_info

示例

从 NumPy 获取 npymath 库所需的信息:

代码语言:javascript
复制
>>> npymath_info = np.distutils.misc_util.get_info('npymath')
>>> npymath_info                                    
{'define_macros': [], 'libraries': ['npymath'], 'library_dirs':
['.../numpy/core/lib'], 'include_dirs': ['.../numpy/core/include']} 

然后,此 info 字典可以作为 Configuration 实例的输入:

代码语言:javascript
复制
config.add_extension('foo', sources=['foo.c'], extra_info=npymath_info) 
代码语言:javascript
复制
numpy.distutils.misc_util.get_language(sources)

从源代码确定语言值(c,f77,f90)

代码语言:javascript
复制
numpy.distutils.misc_util.get_lib_source_files(lib)
代码语言:javascript
复制
numpy.distutils.misc_util.get_mathlibs(path=None)

返回 numpyconfig.h 中的 MATHLIB 行

代码语言:javascript
复制
numpy.distutils.misc_util.get_num_build_jobs()

获取由 setup.py 的–parallel 命令行参数设置的并行构建作业的数量。如果命令没有接收设置,则检查环境变量 NPY_NUM_BUILD_JOBS。如果未设置,则返回系统上的处理器数量,最多为 8 个(以防止系统超载,如果有大量 CPU)。

返回:

outint

可以运行的并行作业数量

代码语言:javascript
复制
numpy.distutils.misc_util.get_numpy_include_dirs()
代码语言:javascript
复制
numpy.distutils.misc_util.get_pkg_info(pkgname, dirs=None)

返回给定包的库信息。

参数:

pkgnamestr

包的名称(应与.ini 文件的名称匹配,不包括扩展名,例如对于文件 foo,包名应为 foo)。

dirs序列,可选

如果给出,应该是一个额外的目录序列,在这些目录中查找 npy-pkg-config 文件。在 NumPy 目录之前搜索这些目录。

返回:

pkginfo类实例

包含构建信息的LibraryInfo实例。

引发:

PkgNotFound

如果找不到包。

参见

Configuration.add_npy_pkg_configConfiguration.add_installed_library

get_info

代码语言:javascript
复制
numpy.distutils.misc_util.get_script_files(scripts)
代码语言:javascript
复制
numpy.distutils.misc_util.gpaths(paths, local_path='', include_non_existing=True)

对路径应用 glob,并在需要时添加 local_path。

代码语言:javascript
复制
numpy.distutils.misc_util.green_text(s)
代码语言:javascript
复制
numpy.distutils.misc_util.has_cxx_sources(sources)

如果 sources 包含 C ++文件,则返回 True

代码语言:javascript
复制
numpy.distutils.misc_util.has_f_sources(sources)

如果 sources 包含 Fortran 文件,则返回 True

代码语言:javascript
复制
numpy.distutils.misc_util.is_local_src_dir(directory)

如果目录是本地目录,则返回 True。

代码语言:javascript
复制
numpy.distutils.misc_util.is_sequence(seq)
代码语言:javascript
复制
numpy.distutils.misc_util.is_string(s)
代码语言:javascript
复制
numpy.distutils.misc_util.mingw32()

在使用 mingw32 环境时返回 True。

代码语言:javascript
复制
numpy.distutils.misc_util.minrelpath(path)

从路径中解析 *.

代码语言:javascript
复制
numpy.distutils.misc_util.njoin(*path)

连接两个或更多的路径名组件 + - 将一个以/分隔的路径名转换为使用 OS 的路径分隔符。- 从路径中解析 *和 *。

可以通过传递 n 个参数(例如 njoin(‘a’,‘b’)),或传递 n 个名称的序列(例如 njoin([‘a’,‘b’])),或这些参数的混合来处理。

代码语言:javascript
复制
numpy.distutils.misc_util.red_text(s)
代码语言:javascript
复制
numpy.distutils.misc_util.sanitize_cxx_flags(cxxflags)

一些标志对 C 有效但对 C ++无效。将它们剪切。

代码语言:javascript
复制
numpy.distutils.misc_util.terminal_has_colors()
代码语言:javascript
复制
numpy.distutils.misc_util.yellow_text(s)

numpy.distutils.ccompiler

原文:numpy.org/doc/1.26/reference/generated/numpy.distutils.ccompiler.html

函数

CCompiler_compile(self, sources[, …])

编译一个或多个源文件。

CCompiler_customize(self, dist[, need_cxx])

对编译器实例进行任何特定于平台的定制。

CCompiler_customize_cmd(self, cmd[, ignore])

使用 distutils 命令自定义编译器。

CCompiler_cxx_compiler(self)

返回 C++编译器。

CCompiler_find_executables(self)

此处无操作,但由 get_version 方法调用,可以被子类重写。

CCompiler_get_version(self[, force, ok_status])

返回编译器版本,如果编译器不可用,则返回 None。

CCompiler_object_filenames(self, …[, …])

返回给定源文件的对象文件的名称。

CCompiler_show_customization(self)

将编译器的定制打印到标准输出。

CCompiler_spawn(self, cmd[, display, env])

在子进程中执行命令。

gen_lib_options(compiler, library_dirs, …)

new_compiler([plat, compiler, verbose, …])

replace_method(klass, method_name, func)

simple_version_match([pat, ignore, start])

版本号简单匹配,用于 CCompiler 和 FCompiler。

numpy.distutils.ccompiler_opt

原文:numpy.org/doc/1.26/reference/generated/numpy.distutils.ccompiler_opt.html

提供 CCompilerOpt 类,用于处理 CPU/硬件优化,从解析命令参数开始,到管理 CPU 基线和可调度特性之间的关系,还生成所需的 C 头文件,最后使用适当的编译器标志编译源代码。

CCompilerOpt 不提供对 CPU 特性的运行时检测,而是仅关注编译器方面,但它创建了可以在最终运行时调度过程中后续使用的抽象 C 头文件。

函数

new_ccompiler_opt(compiler, dispatch_hpath, …)

创建一个新的 ‘CCompilerOpt’ 实例,并生成包含启用的 CPU 基线和可调度特性的平台特定指令集的 #定义和头文件的调度头文件。

CCompilerOpt(ccompiler[, cpu_baseline, …])

一个辅助类用于CCompiler,旨在提供额外的构建选项,以有效地控制与 CPU 特性直接相关的编译器优化。

numpy.distutils.cpuinfo.cpu

原文:numpy.org/doc/1.26/reference/generated/numpy.distutils.cpuinfo.cpu.html

代码语言:javascript
复制
distutils.cpuinfo.cpu = <numpy.distutils.cpuinfo.LinuxCPUInfo object>

numpy.distutils.core.Extension

原文:numpy.org/doc/1.26/reference/generated/numpy.distutils.core.Extension.html

代码语言:javascript
复制
class numpy.distutils.core.Extension(name, sources, include_dirs=None, define_macros=None, undef_macros=None, library_dirs=None, libraries=None, runtime_library_dirs=None, extra_objects=None, extra_compile_args=None, extra_link_args=None, export_symbols=None, swig_opts=None, depends=None, language=None, f2py_options=None, module_dirs=None, extra_c_compile_args=None, extra_cxx_compile_args=None, extra_f77_compile_args=None, extra_f90_compile_args=None)

参数:

namestr

扩展名。

sourcesstr 列表

源文件相对于包顶级目录的位置列表。

extra_compile_argsstr 列表

传递给编译器的额外命令行参数。

extra_f77_compile_argsstr 列表

传递给 fortran77 编译器的额外命令行参数。

extra_f90_compile_argsstr 列表

传递给 fortran90 编译器的额外命令行参数。

方法

has_cxx_sources

has_f2py_sources

numpy.distutils.exec_command

原文:numpy.org/doc/1.26/reference/generated/numpy.distutils.exec_command.html

exec_command

实现了几乎等同于 commands.getstatusoutput 函数的 exec_command 函数,但在 NT、DOS 系统上返回的状态实际上是正确的(虽然返回的状态值可能会有所不同)。此外,exec_command 采用关键字参数来(重新)定义环境变量。

提供函数:

exec_command — 在指定目录中执行命令 在修改后的环境中。 find_executable — 利用环境信息找到一个命令 变量 PATH。相当于 posix 的which命令。

作者:Pearu Peterson pearu@cens.ioc.ee 创建日期:2003 年 1 月 11 日

需要:Python 2.x

成功测试:

os.name

sys.platform

comments

posix

linux2

Debian (sid) Linux, Python 2.1.3+, 2.2.3+, 2.3.3 PyCrust 0.9.3, Idle 1.0.2

posix

linux2

Red Hat 9 Linux, Python 2.1.3, 2.2.2, 2.3.2

posix

sunos5

SunOS 5.9, Python 2.2, 2.3.2

posix

darwin

Darwin 7.2.0, Python 2.3

nt

win32

Windows Me Python 2.3(EE), Idle 1.0, PyCrust 0.7.2 Python 2.1.1 Idle 0.8

nt

win32

Windows 98, Python 2.1.1. Idle 0.8

nt

win32

Cygwin 98-4.10, Python 2.1.1(MSC) - echo 测试失败,即重新定义环境变量可能无效。已修复:不使用 cygwin echo!评论:cmd /c echo也不能工作,但重新定义环境变量可以工作。

posix

cygwin

Cygwin 98-4.10, Python 2.3.3(cygming special)

nt

win32

Windows XP, Python 2.3.3

已知的错误:

  • 从 MSYS 提示符中执行时,向 stderr 发送消息的测试失败,因为在某个时候消息会丢失。

函数

exec_command(command[, execute_in, …])

返回执行命令的状态和输出。

filepath_from_subprocess_output(output)

将子进程使用编码的bytes转换为适合文件系统的str。

find_executable(exe[, path, _cache])

返回可执行文件的完整路径,如果不存在则返回 None。

forward_bytes_to_stdout(val)

将子进程调用的字节直接转发到控制台,而不尝试解码它们。

get_pythonexe()

temp_file_name()

numpy.distutils.log.set_verbosity

原文:numpy.org/doc/1.26/reference/generated/numpy.distutils.log.set_verbosity.html

代码语言:javascript
复制
distutils.log.set_verbosity(v, force=False)

numpy.distutils.system_info.get_info

原文:numpy.org/doc/1.26/reference/generated/numpy.distutils.system_info.get_info.html

代码语言:javascript
复制
distutils.system_info.get_info(name, notfound_action=0)

notfound_action:

0 - 什么也不做 1 - 显示警告消息 2 - 引发错误

numpy.distutils.system_info.get_standard_file

原文:numpy.org/doc/1.26/reference/generated/numpy.distutils.system_info.get_standard_file.html

代码语言:javascript
复制
distutils.system_info.get_standard_file(fname)

返回一个名为’fname’的文件列表,来自于:1)系统范围的目录(本模块的目录位置)2)用户的 HOME 目录(os.environ[‘HOME’])3)本地目录

NumPy distutils - 用户指南

原文:numpy.org/doc/1.26/reference/distutils_guide.html

警告

numpy.distutils 已弃用,并将在 Python >= 3.12 中移除。有关更多详情,请参见 numpy.distutils 的状态和迁移建议

SciPy 结构

目前 SciPy 项目包含两个包:

  • NumPy — 它提供如下包:
    • numpy.distutils - Python distutils 的扩展
    • numpy.f2py - 将 Fortran/C 代码绑定到 Python 的工具
    • numpy.core - 用于替代 Numeric 和 numarray 包的未来版本
    • numpy.lib - 额外实用函数
    • numpy.testing - 用于单元测试的 numpy 风格工具
    • 等等
  • SciPy — 一套用于 Python 的科学工具集。

本文档的目的是描述如何向 SciPy 中添加新工具。

SciPy 包的要求

SciPy 由名为 SciPy 包的 Python 包组成,通过 scipy 命名空间可以提供给 Python 用户使用。每个 SciPy 包可能包含其他 SciPy 包。因此,SciPy 目录树是具有任意深度和宽度的包树。任何 SciPy 包可能依赖于 NumPy 包,但对其他 SciPy 包的依赖应尽可能减少或为零。

一个 SciPy 包除了其源代码外,还包括以下文件和目录:

  • setup.py — 构建脚本
  • __init__.py — 包初始化器
  • tests/ — 单元测试目录

它们的内容如下所述。

setup.py 文件

为了将一个 Python 包添加到 SciPy,其构建脚本 (setup.py) 必须符合某些要求。最重要的要求是包定义一个 configuration(parent_package='',top_path=None) 函数,该函数返回一个适合传递给 numpy.distutils.core.setup(..) 的字典。为了简化构造此字典,numpy.distutils.misc_util 提供了下面描述的 Configuration 类。

SciPy 纯 Python 包示例

下面是一个纯 SciPy 包的最小 setup.py 文件示例:

代码语言:javascript
复制
#!/usr/bin/env python3
def configuration(parent_package='',top_path=None):
    from numpy.distutils.misc_util import Configuration
    config = Configuration('mypackage',parent_package,top_path)
    return config

if __name__ == "__main__":
    from numpy.distutils.core import setup
    #setup(**configuration(top_path='').todict())
    setup(configuration=configuration) 

configuration 函数的参数指定了父 SciPy 包的名称(parent_package)和主 setup.py 脚本的目录位置(top_path)。这些参数和当前包的名称应该传递给 Configuration 构造函数。

Configuration 构造函数有第四个可选参数,package_path,当包文件位于与 setup.py 文件所在目录不同的位置时可以使用。

剩余的Configuration参数都是初始化Configuration实例属性时将使用的关键字参数。通常,这些关键字与setup(..)函数所期望的关键字相同,例如,packages, ext_modules, data_files, include_dirs, libraries, headers, scripts, package_dir等。但是,不建议直接指定这些关键字参数,因为这些关键字参数的内容不会被处理或检查 SciPy 构建系统的一致性。

最后,Configuration具有.todict()方法,它将所有配置数据作为适合传递给setup(..)函数的字典返回。

Configuration实例属性

除了可以通过关键字参数指定给Configuration构造函数的属性之外,Configuration实例(我们以config表示)还具有以下属性,这些属性在编写设置脚本时可能会有用:

  • config.name - 当前软件包的完整名称。可以提取父软件包的名称作为config.name.split('.')
  • config.local_path - 指向当前setup.py文件的路径。
  • config.top_path - 指向主setup.py文件的路径。
Configuration实例方法

config.todict() — 返回适合传递给numpy.distutils.core.setup(..)函数的配置字典。

config.paths(*paths) --- 如有必要,将paths的项应用于``glob.glob(..)。修复相对于config.local_pathpaths项。

config.get_subpackage(subpackage_name,subpackage_path=None) — 返回子软件包配置的列表。在当前目录中查找名称为subpackage_name的子软件包,但也可以通过可选的subpackage_path参数指定路径。如果将subpackage_name指定为None,则子软件包的名称将采用subpackage_path的基本名称。任何用于子软件包名称的*都会按通配符进行展开。

config.add_subpackage(subpackage_name,subpackage_path=None) — 将 SciPy 子软件包配置添加到当前配置中。上面解释了参数的含义和用法,请参见config.get_subpackage()方法。

config.add_data_files(*files) — 将files添加到data_files列表的开头。如果files项是元组,则其第一个元素定义了数据文件相对于软件包安装目录的后缀,第二个元素指定了数据文件的路径。默认情况下,数据文件被复制到软件包安装目录下。例如,

代码语言:javascript
复制
config.add_data_files('foo.dat',
                      ('fun',['gun.dat','nun/pun.dat','/tmp/sun.dat']),
                      'bar/car.dat'.
                      '/full/path/to/can.dat',
                      ) 

将数据文件安装到以下位置

代码语言:javascript
复制
<installation path of config.name package>/
  foo.dat
  fun/
    gun.dat
    pun.dat
    sun.dat
  bar/
    car.dat
  can.dat 

数据文件的路径可以是一个不带参数并返回数据文件路径的函数 —— 当在构建软件包时生成数据文件时,这是非常有用的。(XXX:解释确切调用这些函数的步骤)

config.add_data_dir(data_path) — 递归地将data_path目录添加到data_files中。从data_path开始的整个目录树将被复制到包安装目录下。如果data_path是一个元组,则它的第一个元素定义了数据文件被复制的后缀,相对于包安装目录,第二个元素指定了数据目录的路径。默认情况下,数据目录将被复制到包安装目录下的data_path的基本名称下。例如,

代码语言:javascript
复制
config.add_data_dir('fun')  # fun/ contains foo.dat bar/car.dat
config.add_data_dir(('sun','fun'))
config.add_data_dir(('gun','/full/path/to/fun')) 

将数据文件安装到以下位置

代码语言:javascript
复制
<installation path of config.name package>/
  fun/
     foo.dat
     bar/
        car.dat
  sun/
     foo.dat
     bar/
        car.dat
  gun/
     foo.dat
     bar/
        car.dat 

config.add_include_dirs(*paths) — 将paths添加到include_dirs列表的开头。这个列表对当前包的所有扩展模块可见。

config.add_headers(*files) — 将files添加到headers列表的开头。默认情况下,头文件将安装在<prefix>/include/pythonX.X/<config.name.replace('.','/')>/目录下。如果files项是一个元组,则它的第一个参数指定了相对于<prefix>/include/pythonX.X/路径的安装后缀。这是一个 Python distutils 方法;在 NumPy 和 SciPy 中应该使用config.add_data_files(*files)

config.add_scripts(*files) — 将files添加到scripts列表的开头。脚本将安装在<prefix>/bin/目录下。

config.add_extension(name,sources,**kw) — 创建并将一个Extension实例添加到ext_modules列表中。第一个参数name定义了扩展模块的名称,该扩展模块将安装在config.name包下。第二个参数是一个源列表。add_extension方法还接受将传递给Extension构造函数的关键字参数。允许的关键字列表如下:include_dirsdefine_macrosundef_macroslibrary_dirslibrariesruntime_library_dirsextra_objectsextra_compile_argsextra_link_argsexport_symbolsswig_optsdependslanguagef2py_optionsmodule_dirsextra_infoextra_f77_compile_argsextra_f90_compile_args

请注意,config.paths方法适用于可能包含路径的所有列表。extra_info是一个字典或字典列表,其内容将追加到关键字参数。depends列表包含扩展模块源代码依赖的文件或目录路径。如果depends列表中的任何路径都比扩展模块新,那么模块将被重新构建。

源列表可能包含函数(‘源生成器’),其模式为def <funcname>(ext, build_dir): return <source(s) or None>。如果funcname返回None,则不会生成任何源代码。如果所有源生成器处理后Extension实例没有源代码,那么不会构建扩展模块。这是有条件地定义扩展模块的推荐方法。源生成器函数由numpy.distutilsbuild_src子命令调用。

例如,这是一个典型的源生成器函数:

代码语言:javascript
复制
def generate_source(ext,build_dir):
    import os
    from distutils.dep_util import newer
    target = os.path.join(build_dir,'somesource.c')
    if newer(target,__file__):
        # create target file
    return target 

第一个参数包含 Extension 实例,可以用于访问其属性,如dependssources等列表,并在构建过程中对其进行修改。第二个参数给出了一个构建目录的路径,在将文件写入磁盘时必须使用该目录。

config.add_library(name, sources, **build_info) — 向libraries列表添加一个库。允许的关键字参数有dependsmacrosinclude_dirsextra_compiler_argsf2py_optionsextra_f77_compile_argsextra_f90_compile_args。有关参数的更多信息,请参见.add_extension()方法。

config.have_f77c() — 如果 Fortran 77 编译器可用,则返回 True(即:简单的 Fortran 77 代码编译成功)。

config.have_f90c() — 如果 Fortran 90 编译器可用,则返回 True(即:简单的 Fortran 90 代码编译成功)。

config.get_version() — 返回当前包的版本字符串,如果无法检测到版本信息,则返回None。该方法扫描文件__version__.py<packagename>_version.pyversion.py__svn_version__.py以查找字符串变量version__version__<packagename>_version

config.make_svn_version_py() — 向data_files列表附加一个数据函数,该函数将生成__svn_version__.py文件到当前包目录。当 Python 退出时,将从源目录中删除该文件。

config.get_build_temp_dir() — 返回一个临时目录的路径。这是构建临时文件的地方。

config.get_distribution() — 返回 distutils 的Distribution实例。

config.get_config_cmd() — 返回numpy.distutils配置命令实例。

config.get_info(*names)

使用模板转换.src文件

NumPy distutils 支持自动转换命名为.src 的源文件。该功能可用于维护非常相似的代码块,只需要在块之间进行简单的更改。在设置的构建阶段,如果遇到名为.src 的模板文件,则会从模板构造一个名为的新文件,并将其放置在构建目录中以供使用。支持两种模板转换形式。第一种形式用于名为.ext.src 的文件,其中 ext 是一个已识别的 Fortran 扩展名(f、f90、f95、f77、for、ftn、pyf)。第二种形式用于所有其他情况。 ### Fortran 文件

此模板转换器将根据‘<…>’中的规则复制文件中所有的函数子程序块,名字中含有‘<…>’的。‘<…>’中以逗号分隔的单词的数量决定了块的重复次数。这些单词指示了在每个块中将重复规则‘<…>’替换为什么内容。块中的所有重复规则必须包含相同数量的逗号分隔的单词,以指示该块应该重复多少次。如果重复规则中的单词需要逗号、箭头或右箭头,则在其前面添加反斜杠‘ '。如果重复规则中的单词与‘ <index>’匹配,则会被替换为相同重复规范中的第个单词。重复规则有两种形式:命名和短形式。

命名的重复规则

命名的重复规则在一个块中多次使用相同重复集时很有用。它使用<rule1=item1, item2, item3,…, itemN>的格式指定,其中 N 是应该重复该块的次数。在每个块的重复中,整个表达式‘<…>’将首先替换为 item1,然后替换为 item2,以此类推,直到完成 N 次重复。一旦引入了命名的重复规范,相同的重复规则可以通过只引用名称(即)在当前块中使用。

短形式的重复规则

短形式的重复规则的格式为<item1, item2, item3, …, itemN>。该规则指定整个表达式‘<…>’应首先替换为 item1,然后替换为 item2,以此类推,直到完成 N 次重复。

预定义名称

可用的预定义命名重复规则如下:

  • <prefix=s,d,c,z>
  • <_c=s,d,c,z>
  • <_t=real, double precision, complex, double complex>
  • <ftype=real, double precision, complex, double complex>
  • <ctype=float, double, complex_float, complex_double>
  • <ftypereal=float, double precision, \0, \1>
  • <ctypereal=float, double, \0, \1>
其他文件

非 Fortran 文件使用单独的语法来定义应使用类似于 Fortran 特定重复的命名重复规则的模板块的变量扩展。

NumPy Distutils 预处理以自定义模板语言编写的 C 源文件(扩展名:.c.src)以生成 C 代码。@符号用于包装宏样式的变量,以实现可能描述(例如)一组数据类型的字符串替换机制。

模板语言块由/**begin repeat/**end repeat**/行进行界定,这些界定行也可以使用连续编号的界定行(如/**begin repeat1/**end repeat1**/)进行嵌套:

  1. /**begin repeat单独一行标志着应该重复的段的开始。
  2. 使用#name=item1, item2, item3, ..., itemN#定义命名变量扩展,并放置在连续的行上。这些变量会在每个重复块中被相应的词替换。同一重复块中的所有命名变量必须定义相同数量的词。
  3. 在为命名变量指定重复规则时,item*Nitem, item, ..., item重复 N 次的简写。此外,结合*N的括号可用于对应多个应该重复的项进行分组。因此,#name=(item1, item2)*4#等同于#name=item1, item2, item1, item2, item1, item2, item1, item2#
  4. 单独一行上的*/标记结束变量扩展命名。下一行是将使用命名规则重复的第一行。
  5. 在要重复的块内,应扩展的变量被指定为@name@
  6. 单独一行上的/**end repeat**/标记前一行为要重复的块的最后一行。
  7. NumPy C 源代码中的循环可能具有@TYPE@变量,用于字符串替换,预处理为具有多个字符串(如INTLONGUINTULONG等)的通常相同的循环。因此,@TYPE@样式语法通过模仿具有通用类型支持的语言来减少代码重复和维护负担。

以上规则在以下模板源示例中可能更清晰:

代码语言:javascript
复制
 1  /* TIMEDELTA to non-float types */
 2
 3  /**begin repeat 4 *
 5 * #TOTYPE = BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG,
 6 *           LONGLONG, ULONGLONG, DATETIME,
 7 *           TIMEDELTA#
 8 * #totype = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
 9 *           npy_long, npy_ulong, npy_longlong, npy_ulonglong,
10 *           npy_datetime, npy_timedelta#
11 */
12
13  /**begin repeat1 14 *
15 * #FROMTYPE = TIMEDELTA#
16 * #fromtype = npy_timedelta#
17 */
18  static  void
19  @FROMTYPE@_to_@TOTYPE@(void *input, void *output, npy_intp n,
20  void  *NPY_UNUSED(aip),  void  *NPY_UNUSED(aop))
21  {
22  const  @fromtype@ *ip = input;
23  @totype@ *op = output;
24
25  while  (n--)  {
26  *op++  =  (@totype@)*ip++;
27  }
28  }
29  /**end repeat1**/ 30
31  /**end repeat**/ 

通用类型 C 源文件的预处理(无论是 NumPy 本身还是使用 NumPy Distutils 的任何第三方包中的文件)由conv_template.py执行。在构建过程中由这些模块生成的特定类型 C 文件(扩展名:.c)已准备好进行编译。这种通用类型的形式也支持 C 头文件(预处理以生成.h文件)。

numpy.distutils.misc_util中的有用函数
  • get_numpy_include_dirs() — 返回 NumPy 基础包含目录的列表。NumPy 基础包含目录包含诸如numpy/arrayobject.hnumpy/funcobject.h等头文件。对于已安装的 NumPy,返回的列表长度为 1,但在构建 NumPy 时,列表可能包含更多目录,例如,numpy/base/setup.py文件生成并被numpy头文件使用的config.h文件路径。
  • append_path(prefix,path) — 智能地将path附加到prefix
  • gpaths(paths, local_path='') — 对路径应用 glob 并在需要时添加local_path前缀。
  • njoin(*path) — 连接路径名组件+将/分隔路径转换为os.sep分隔路径并解析路径中的...。例如,njoin('a',['b','./c'],'..','g') -> os.path.join('a','b','g')
  • minrelpath(path) — 解析path中的点号。
  • rel_path(path, parent_path) — 返回相对于parent_pathpath
  • def get_cmd(cmdname,_cache={}) — 返回numpy.distutils命令实例。
  • all_strings(lst)
  • has_f_sources(sources)
  • has_cxx_sources(sources)
  • filter_sources(sources) — 返回c_sources, cxx_sources, f_sources, fmodule_sources
  • get_dependencies(sources)
  • is_local_src_dir(directory)
  • get_ext_source_files(ext)
  • get_script_files(scripts)
  • get_lib_source_files(lib)
  • get_data_files(data)
  • dot_join(*args) — 用点连接非零参数。
  • get_frame(level=0) — 返回给定级别调用堆栈中的帧对象。
  • cyg2win32(path)
  • mingw32() — 在使用 mingw32 环境时返回True
  • terminal_has_colors(), red_text(s), green_text(s), yellow_text(s), blue_text(s), cyan_text(s)
  • get_path(mod_name,parent_path=None) — 在给定时,返回相对于 parent_path 的模块路径。也处理__main____builtin__模块。
  • allpath(name) — 在name中将/替换为os.sep
  • cxx_ext_match, fortran_ext_match, f90_ext_match, f90_module_name_match
numpy.distutils.system_info 模块
  • get_info(name,notfound_action=0)
  • combine_paths(*args,**kws)
  • show_all()
numpy.distutils.cpuinfo 模块
  • cpuinfo
numpy.distutils.log 模块
  • set_verbosity(v)
numpy.distutils.exec_command 模块
  • get_pythonexe()
  • find_executable(exe, path=None)
  • exec_command( command, execute_in='', use_shell=None, use_tee=None, **env )

__init__.py 文件

典型 SciPy __init__.py 的头部是:

代码语言:javascript
复制
"""
Package docstring, typically with a brief description and function listing.
"""

# import functions into module namespace
from .subpackage import *
...

__all__ = [s for s in dir() if not s.startswith('_')]

from numpy.testing import Tester
test = Tester().test
bench = Tester().bench 

NumPy Distutils 中的额外功能

在 setup.py 脚本中为库指定 config_fc 选项

可以在 setup.py 脚本中指定 config_fc 选项。例如,使用

config.add_library(‘library’, sources=[…], config_fc={‘noopt’😦file,1)})

将编译 library 源文件时不使用优化标志。

建议只指定那些与编译器无关的 config_fc 选项。

从源代码中获取额外的 Fortran 77 编译器选项

一些旧的 Fortran 代码需要特殊的编译器选项才能正确工作。为了指定每个源文件的编译器选项,numpy.distutils Fortran 编译器寻找以下模式:

代码语言:javascript
复制
CF77FLAGS(<fcompiler type>) = <fcompiler f77flags> 

在源代码的前 20 行中,并针对指定类型的 fcompiler 使用 f77flags(第一个字符 C 可选)。

TODO: 这个功能也可以很容易地扩展到 Fortran 90 代码上。如果您需要这样的功能,请告诉我们。

SciPy 结构

当前 SciPy 项目包括两个包:

  • NumPy — 提供类似以下包:
    • numpy.distutils - Python distutils 的扩展
    • numpy.f2py - 一个将 Fortran/C 代码绑定到 Python 的工具
    • numpy.core - 取代 Numeric 和 numarray 包的未来包裹
    • numpy.lib - 额外的实用函数
    • numpy.testing - 类似于 numpy 的单元测试工具
  • SciPy — 为 Python 提供的一批科学工具。

本文旨在描述如何向 SciPy 添加新工具。

SciPy 包的要求

SciPy 由 Python 包组成,称为 SciPy 包,通过scipy名称空间提供给 Python 用户。每个 SciPy 包可能包含其他 SciPy 包。以此类推。因此,SciPy 目录树是具有任意深度和宽度的包树。任何 SciPy 包可能依赖于 NumPy 包,但对其他 SciPy 包的依赖应保持最小或零。

除了源文件之外,SciPy 包还包含以下文件和目录:

  • setup.py — 构建脚本
  • __init__.py — 包初始化文件
  • tests/ — 单元测试目录

它们的内容如下。

setup.py文件

要将 Python 包添加到 SciPy,其构建脚本(setup.py)必须满足一定的要求。最重要的要求是该包定义一个返回适合传递给numpy.distutils.core.setup(..)的字典的configuration(parent_package='',top_path=None)函数。为了简化构建此字典的过程,numpy.distutils.misc_util提供了下面描述的Configuration类。

SciPy 纯 Python 包示例

以下是一个纯 SciPy 包的最小setup.py文件示例:

代码语言:javascript
复制
#!/usr/bin/env python3
def configuration(parent_package='',top_path=None):
    from numpy.distutils.misc_util import Configuration
    config = Configuration('mypackage',parent_package,top_path)
    return config

if __name__ == "__main__":
    from numpy.distutils.core import setup
    #setup(**configuration(top_path='').todict())
    setup(configuration=configuration) 

configuration函数的参数指定父 SciPy 包的名称(parent_package)和主setup.py脚本的目录位置(top_path)。这些参数,连同当前包的名称,应传递给Configuration构造函数。

Configuration构造函数有一个第四个可选参数package_path,用于当包文件位于不同于setup.py文件目录的位置时使用。

剩余的Configuration参数都是将用于初始化Configuration实例属性的关键字参数。通常,这些关键字与setup(..)函数所期望的关键字相同,例如packagesext_modulesdata_filesinclude_dirslibrariesheadersscriptspackage_dir等。但是,不建议直接指定这些关键字,因为这些关键字参数的内容不会被处理或检查 SciPy 构建系统的一致性。

最后,Configuration有一个.todict()方法,将所有配置数据作为适合传递给setup(..)函数的字典返回。

Configuration实例属性

除了可以通过关键字参数指定的属性外,Configuration实例(我们将其标记为config)具有以下对于编写安装脚本很有用的属性:

  • config.name - 当前包的完整名称。可以提取父包的名称为config.name.split('.')
  • config.local_path - 当前setup.py文件的路径位置。
  • config.top_path - 主setup.py文件的路径位置。
Configuration实例方法

config.todict() — 返回适合传递给numpy.distutils.core.setup(..)函数的配置字典。

config.paths(*paths) --- 如果必要,对paths的项目应用glob.glob(…)。修复相对于config.local_pathpaths`项目。

config.get_subpackage(subpackage_name,subpackage_path=None) — 返回子包配置的列表。在当前目录下查找名为subpackage_name的子包,但也可以通过可选的subpackage_path参数指定路径。如果subpackage_name指定为None,则子包名称将使用subpackage_path的基本名称。任何用于子包名称的*都会被扩展为通配符。

config.add_subpackage(subpackage_name,subpackage_path=None) — 向当前配置添加 SciPy 子包配置。解释参数的含义和用法如上所述,请参阅config.get_subpackage()方法。

config.add_data_files(*files) — 将files添加到data_files列表的开头。如果files项目是一个元组,则其第一个元素定义了将数据文件复制到包安装目录的后缀,第二个元素指定了数据文件的路径。默认情况下,数据文件将复制到包安装目录下。例如,

代码语言:javascript
复制
config.add_data_files('foo.dat',
                      ('fun',['gun.dat','nun/pun.dat','/tmp/sun.dat']),
                      'bar/car.dat'.
                      '/full/path/to/can.dat',
                      ) 

将数据文件安装到以下位置

代码语言:javascript
复制
<installation path of config.name package>/
  foo.dat
  fun/
    gun.dat
    pun.dat
    sun.dat
  bar/
    car.dat
  can.dat 

数据文件的路径可以是一个不带参数并返回路径(s)到数据文件的函数——当构建包时生成数据文件时,这是一个有用的功能(XXX:具体解释这个函数什么时候被调用)

config.add_data_dir(data_path) — 递归地将目录data_path添加到data_files中。从data_path开始的整个目录树将在包安装目录下复制。如果data_path是一个元组,则其第一个元素定义了复制数据文件的后缀,相对于包安装目录,第二个元素指定了数据目录的路径。默认情况下,数据目录被复制到包安装目录下,以data_path的基本名称命名。例如,

代码语言:javascript
复制
config.add_data_dir('fun')  # fun/ contains foo.dat bar/car.dat
config.add_data_dir(('sun','fun'))
config.add_data_dir(('gun','/full/path/to/fun')) 

将数据文件安装到以下位置

代码语言:javascript
复制
<installation path of config.name package>/
  fun/
     foo.dat
     bar/
        car.dat
  sun/
     foo.dat
     bar/
        car.dat
  gun/
     foo.dat
     bar/
        car.dat 

config.add_include_dirs(*paths) — 将paths添加到include_dirs列表的开头。这个列表将对当前包的所有扩展模块可见。

config.add_headers(*files) — 将files添加到headers列表的开头。默认情况下,头文件将安装在<prefix>/include/pythonX.X/<config.name.replace('.','/')>/目录下。如果files项目是一个元组,那么它的第一个参数指定相对于<prefix>/include/pythonX.X/路径的安装后缀。这是一个 Python distutils 方法;在 NumPy 和 SciPy 中,建议使用config.add_data_files(*files)

config.add_scripts(*files) — 将files添加到scripts列表的开头。脚本将安装在<prefix>/bin/目录下。

config.add_extension(name,sources,**kw) — 创建并将一个 Extension 实例添加到 ext_modules 列表中。第一个参数 name 定义了扩展模块的名称,该模块将安装在 config.name 包下。第二个参数是一个源列表。add_extension 方法还接受传递给 Extension 构造函数的关键字参数。允许的关键字列表如下:include_dirsdefine_macrosundef_macroslibrary_dirslibrariesruntime_library_dirsextra_objectsextra_compile_argsextra_link_argsexport_symbolsswig_optsdependslanguagef2py_optionsmodule_dirsextra_infoextra_f77_compile_argsextra_f90_compile_args

请注意,config.paths 方法适用于可能包含路径的所有列表。extra_info 是一个字典或字典列表,其内容将附加到关键字参数中。depends 列表包含了扩展模块的源文件依赖的文件或目录路径。如果 depends 列表中的任何路径新于扩展模块,则将重新构建该模块。

源列表可能包含具有模式 def <funcname>(ext, build_dir): return <source(s) or None> 的函数(‘源生成器’)。 如果 funcname 返回 None,则不会生成任何源。如果 Extension 实例在处理所有源生成器后没有任何源,那么不会构建扩展模块。这是有条件地定义扩展模块的推荐方法。源生成器函数由 numpy.distutilsbuild_src 子命令调用。

例如,这是一个典型的源生成器函数示例:

代码语言:javascript
复制
def generate_source(ext,build_dir):
    import os
    from distutils.dep_util import newer
    target = os.path.join(build_dir,'somesource.c')
    if newer(target,__file__):
        # create target file
    return target 

第一个参数包含了 Extension 实例,可以用于访问其属性,如 dependssources 等列表,并在构建过程中修改它们。第二个参数提供了一个构建目录的路径,在创建文件到磁盘时必须使用该路径。

config.add_library(name, sources, **build_info) — 将库添加到 libraries 列表中。允许的关键字参数包括 dependsmacrosinclude_dirsextra_compiler_argsf2py_optionsextra_f77_compile_argsextra_f90_compile_args。有关参数的更多信息,请参阅.add_extension() 方法。

config.have_f77c() — 如果 Fortran 77 编译器可用(即:简单的 Fortran 77 代码编译成功),则返回 True。

config.have_f90c() — 如果 Fortran 90 编译器可用(即:简单的 Fortran 90 代码编译成功),则返回 True。

config.get_version() — 返回当前包的版本字符串,如果无法检测到版本信息,则返回 None。该方法扫描文件 __version__.py<packagename>_version.pyversion.py__svn_version__.py,以查找字符串变量 version__version__<packagename>_version

config.make_svn_version_py() — 向data_files列表添加一个数据函数,该函数将生成__svn_version__.py文件到当前包目录。Python 退出时,该文件将从源目录中删除。

config.get_build_temp_dir() — 返回临时目录路径。这是应该构建临时文件的地方。

config.get_distribution() — 返回 distutils Distribution 实例。

config.get_config_cmd() — 返回 numpy.distutils 配置命令实例。

config.get_info(*names)

使用模板转换.src文件

NumPy distutils 支持自动转换命名为.src 的源文件。这个功能可用于在块之间保持非常相似的代码,只需要进行简单的更改。在设置的构建阶段期间,如果遇到名为.src 的模板文件,将从模板构造一个名为的新文件,并将其放置在构建目录中以供使用。支持两种模板转换形式。第一种形式适用于文件名为.ext.src,其中 ext 是一个已识别的 Fortran 扩展名(f,f90,f95,f77,for,ftn,pyf)。第二种形式用于所有其他情况。### Fortran 文件

此模板转换器将根据‘<…>’中的规则,复制文件中所有的函数子例程块,并以包含‘<…>’的名称来重复。‘<…>’中用逗号分隔的单词的数量决定了块被重复的次数。这些单词指示了在每个块中‘<…>’应该用什么替换。一个块中的所有重复规则必须包含相同数量的逗号分隔的单词,表明这个块应该被重复的次数。如果重复规则中的单词需要有逗号,左箭头或右箭头,那么在其前面加上反斜杠’ '。如果重复规则中的单词匹配‘<index>’,那么它将被替换为相同重复规范中的第个单词。重复规则有两种形式:命名和简短。

命名重复规则

当同一组重复必须多次在一个块中使用时,命名重复规则非常有用。它使用<rule1=item1, item2, item3,…, itemN>来指定,其中 N 是块应该重复的次数。在块的每次重复中,整个表达式‘<…>’首先会被 item1 替换,然后被 item2 替换,依此类推,直到完成 N 次重复。一旦引入了命名重复规范,就可以通过只引用名称(即<规则 1>)在当前块中使用相同的重复规则。

简短重复规则

简短重复规则看起来像<item1, item2, item3, …, itemN>。规则指定整个表达式‘<…>’应首先用 item1 替换,然后用 item2 替换,依此类推,直到 N 次重复完成。

预定义名称

以下是可用的预定义命名重复规则:

  • <prefix=s,d,c,z>
  • <_c=s,d,c,z>
  • <_t=real, double precision, complex, double complex>
  • <ftype=real, double precision, complex, double complex>
  • <ctype=float, double, complex_float, complex_double>
  • <ftypereal=float, double precision, \0, \1>
  • <ctypereal=float, double, \0, \1>
其他文件

非 Fortran 文件使用单独的语法来定义应使用类似于 Fortran 特定重复规则的变量扩展的模板块。

NumPy Distutils 对使用自定义模板语言编写的 C 源文件(扩展名:.c.src)进行预处理以生成 C 代码。@符号用于包装宏样式的变量,以提供描述(例如)一组数据类型的字符串替换机制。

模板语言块由/**begin repeat/**end repeat**/行界定,这些行也可以使用连续编号的界定行进行嵌套,例如/**begin repeat1/**end repeat1**/

  1. 单独一行上的/**begin repeat标记了应重复的段的开始。
  2. 使用#name=item1, item2, item3, ..., itemN#定义命名变量扩展,并将其放置在连续的行上。这些变量在每个重复块中与相应的单词替换。同一重复块中的所有命名变量必须定义相同数量的单词。
  3. 在为命名变量指定重复规则时,item*N表示item, item, ..., item重复 N 次的简写。此外,结合*N的括号可以用于分组多个应该重复的项。因此,#name=(item1, item2)*4#相当于#name=item1, item2, item1, item2, item1, item2, item1, item2#
  4. 单独一行的*/标记了变量扩展命名的结束。下一行是将使用命名规则重复的第一行。
  5. 在要重复的块内,指定要展开的变量为@name@
  6. 单独一行的/**end repeat**/标记了前一行作为要重复块的最后一行。
  7. NumPy C 源代码中的循环可能具有@TYPE@变量,用于字符串替换,该变量经预处理后成为多个完全相同的循环,其中包含INTLONGUINTULONG等多个字符串。因此,@TYPE@样式的语法通过模仿具有通用类型支持的语言来减少代码重复和维护负担。

以下是上述规则在以下模板源示例中更为明确的示例:

代码语言:javascript
复制
 1  /* TIMEDELTA to non-float types */
 2
 3  /**begin repeat 4 *
 5 * #TOTYPE = BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG,
 6 *           LONGLONG, ULONGLONG, DATETIME,
 7 *           TIMEDELTA#
 8 * #totype = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
 9 *           npy_long, npy_ulong, npy_longlong, npy_ulonglong,
10 *           npy_datetime, npy_timedelta#
11 */
12
13  /**begin repeat1 14 *
15 * #FROMTYPE = TIMEDELTA#
16 * #fromtype = npy_timedelta#
17 */
18  static  void
19  @FROMTYPE@_to_@TOTYPE@(void *input, void *output, npy_intp n,
20  void  *NPY_UNUSED(aip),  void  *NPY_UNUSED(aop))
21  {
22  const  @fromtype@ *ip = input;
23  @totype@ *op = output;
24
25  while  (n--)  {
26  *op++  =  (@totype@)*ip++;
27  }
28  }
29  /**end repeat1**/ 30
31  /**end repeat**/ 

对于通用类型的 C 源文件(无论是在 NumPy 本身还是在使用 NumPy Distutils 的任何第三方包中),都使用conv_template.py进行预处理。在构建过程中,这些模块生成的特定类型的 C 文件(扩展名:.c)已经准备好编译了。此类通用类型也支持 C 头文件(预处理为.h文件)。

numpy.distutils.misc_util中的实用函数
  • get_numpy_include_dirs() — 返回 NumPy 基本包含目录列表。NumPy 基本包含目录包含诸如numpy/arrayobject.hnumpy/funcobject.h等头文件。对于已安装的 NumPy,返回的列表长度为 1,但构建 NumPy 时,该列表可能包含更多目录,例如,numpy/base/setup.py文件生成并被numpy头文件使用的config.h文件路径��
  • append_path(prefix,path) — 将path智能地附加到prefix
  • gpaths(paths, local_path='') — 对路径应用 glob,并在必要时添加local_path前缀。
  • njoin(*path) — 连接路径名组件+将/分隔的路径转换为os.sep分隔的路径并从路径中解析...。例如,njoin('a',['b','./c'],'..','g') -> os.path.join('a','b','g')
  • minrelpath(path) — 解析path中的点。
  • rel_path(path, parent_path) — 返回相对于parent_pathpath
  • def get_cmd(cmdname,_cache={}) — 返回numpy.distutils命令实例。
  • all_strings(lst)
  • has_f_sources(sources)
  • has_cxx_sources(sources)
  • filter_sources(sources) — 返回c_sources, cxx_sources, f_sources, fmodule_sources
  • get_dependencies(sources)
  • is_local_src_dir(directory)
  • get_ext_source_files(ext)
  • get_script_files(scripts)
  • get_lib_source_files(lib)
  • get_data_files(data)
  • dot_join(*args) — 用点连接非零参数。
  • get_frame(level=0) — 返回调用栈中给定级别的 frame 对象。
  • cyg2win32(path)
  • mingw32() — 在使用 mingw32 环境时返回True
  • terminal_has_colors(), red_text(s), green_text(s), yellow_text(s), blue_text(s), cyan_text(s)
  • get_path(mod_name,parent_path=None) — 在给定时返回模块相对于 parent_path 的路径。还处理__main____builtin__模块。
  • allpath(name) — 在name中将/替换为os.sep
  • cxx_ext_match, fortran_ext_match, f90_ext_match, f90_module_name_match
numpy.distutils.system_info模块
  • get_info(name,notfound_action=0)
  • combine_paths(*args,**kws)
  • show_all()
numpy.distutils.cpuinfo模块
  • cpuinfo
numpy.distutils.log模块
  • set_verbosity(v)
numpy.distutils.exec_command模块
  • get_pythonexe()
  • find_executable(exe, path=None)
  • exec_command( command, execute_in='', use_shell=None, use_tee=None, **env )
SciPy 纯 Python 软件包示例

下面是用于纯 SciPy 软件包的最小setup.py文件示例:

代码语言:javascript
复制
#!/usr/bin/env python3
def configuration(parent_package='',top_path=None):
    from numpy.distutils.misc_util import Configuration
    config = Configuration('mypackage',parent_package,top_path)
    return config

if __name__ == "__main__":
    from numpy.distutils.core import setup
    #setup(**configuration(top_path='').todict())
    setup(configuration=configuration) 

configuration函数的参数指定父 SciPy 软件包的名称(parent_package)和主setup.py脚本的目录位置(top_path)。这些参数以及当前软件包的名称应传递给Configuration构造函数。

Configuration构造函数有第四个可选参数package_path,可在软件包文件位于与setup.py文件目录不同的位置时使用。

剩余的Configuration参数都是Configuration实例属性的关键字参数的初始化值。通常,这些关键字与setup(..)函数期望的关键字是相同的,例如,packagesext_modulesdata_filesinclude_dirslibrariesheadersscriptspackage_dir等。然而,不建议直接指定这些关键字,因为这些关键字参数的内容不会被处理或检查 SciPy 构建系统的一致性。

最后,Configuration有一个.todict()方法,它返回所有配置数据,以字典的形式适合传递给setup(..)函数。

Configuration实例的属性

除了可以通过Configuration构造函数的关键参数指定的属性之外,Configuration实例(假设为config)还有以下属性,可以在编写设置脚本时很有用:

  • config.name - 当前软件包的完整名称。父软件包的名称可以通过config.name.split('.')来提取。
  • config.local_path - 当前setup.py文件的路径。
  • config.top_path - 主setup.py文件的路径。
Configuration实例的方法

config.todict() — 返回适合传递给numpy.distutils.core.setup(..)函数的配置字典。

config.paths(*paths) --- 如果有必要,对paths的项应用``glob.glob(..)。修复相对于config.local_pathpaths项。

config.get_subpackage(subpackage_name,subpackage_path=None) — 返回子软件包配置的列表。子软件包在当前目录下寻找,名称为subpackage_name,但路径也可以通过可选的subpackage_path参数指定。如果subpackage_name指定为None,则子软件包名称将取subpackage_path的基本名称。任何用于子软件包名称的*都会被扩展为通配符。

config.add_subpackage(subpackage_name,subpackage_path=None) — 将 SciPy 子软件包配置添加到当前配置。关于参数的意义和用法已在上文中解释过,参见config.get_subpackage()方法。

config.add_data_files(*files) — 将files加入data_files列表的最前面。如果files是一个元组,则其第一个元素定义了数据文件的后缀,相对于软件包安装目录的位置,第二个元素指定了数据文件的路径。默认情况下,数据文件将被复制到软件包安装目录下。例如,

代码语言:javascript
复制
config.add_data_files('foo.dat',
                      ('fun',['gun.dat','nun/pun.dat','/tmp/sun.dat']),
                      'bar/car.dat'.
                      '/full/path/to/can.dat',
                      ) 

将数据文件安装到以下位置

代码语言:javascript
复制
<installation path of config.name package>/
  foo.dat
  fun/
    gun.dat
    pun.dat
    sun.dat
  bar/
    car.dat
  can.dat 

数据文件的路径可以是一个不带参数并返回路径的函数 —— 这在生成软件包时生成数据文件时非常有用。(XXX:解释一下什么时候确切地调用这个函数)

config.add_data_dir(data_path) — 递归地将目录data_path添加到data_files中。从data_path开始的整个目录树将被复制到包安装目录下。 如果data_path是一个元组,那么它的第一个元素定义了将数据文件复制到的后缀的相对于包安装目录的位置,第二个元素指定了数据目录的路径。默认情况下,数据目录被复制到基础data_path的包安装目录下。例如,

代码语言:javascript
复制
config.add_data_dir('fun')  # fun/ contains foo.dat bar/car.dat
config.add_data_dir(('sun','fun'))
config.add_data_dir(('gun','/full/path/to/fun')) 

将数据文件安装到以下位置

代码语言:javascript
复制
<installation path of config.name package>/
  fun/
     foo.dat
     bar/
        car.dat
  sun/
     foo.dat
     bar/
        car.dat
  gun/
     foo.dat
     bar/
        car.dat 

config.add_include_dirs(*paths) — 将paths添加到include_dirs列表的开头。这个列表将对当前包的所有扩展模块可见。

config.add_headers(*files) — 将files添加到headers列表的开头。默认情况下,头文件将安装在<prefix>/include/pythonX.X/<config.name.replace('.','/')>/目录下。 如果files项是一个元组,那么它的第一个参数指定了相对于<prefix>/include/pythonX.X/路径的安装后缀。 这是一个 Python distutils 方法;NumPy 和 SciPy 不鼓励使用它,而是使用config.add_data_files(*files)

config.add_scripts(*files) — 将files添加到scripts列表的开头。脚本将安装在<prefix>/bin/目录下。

config.add_extension(name,sources,**kw) — 创建并将一个Extension实例添加到ext_modules列表中。第一个参数name定义了扩展模块的名称,该模块将安装在config.name包下。第二个参数是一个来源列表。 add_extension方法还接受传递给Extension构造函数的关键字参数。允许的关键字参数列表如下:include_dirsdefine_macrosundef_macroslibrary_dirslibrariesruntime_library_dirsextra_objectsextra_compile_argsextra_link_argsexport_symbolsswig_optsdependslanguagef2py_optionsmodule_dirsextra_infoextra_f77_compile_argsextra_f90_compile_args

注意,config.paths 方法应用于所有可能包含路径的列表。extra_info 是一个字典或字典列表,其内容将附加到关键字参数中。列表depends包含到扩展模块源的文件或目录的路径。如果depends列表中的任何路径都比扩展模块新,那么模块将被重新构建。

来源列表可能包含函数(‘源生成器’),其模式为def <funcname>(ext, build_dir): return <source(s) or None>。如果funcname返回None,则不会生成任何源。如果Extension实例在处理所有源生成器后没有源,那么将不会构建任何扩展模块。这是有条件地定义扩展模块的推荐方式。源生成器函数由numpy.distutilsbuild_src子命令调用。

例如,这是一个典型的源生成器函数:

代码语言:javascript
复制
def generate_source(ext,build_dir):
    import os
    from distutils.dep_util import newer
    target = os.path.join(build_dir,'somesource.c')
    if newer(target,__file__):
        # create target file
    return target 

第一个参数包含 Extension 实例,可以用于访问其属性,如dependssources等列表,并在构建过程中修改它们。第二个参数提供了一个构建目录的路径,必须在将文件写入磁盘时使用。

config.add_library(name, sources, **build_info) — 将库添加到libraries列表中。允许的关键字参数有dependsmacrosinclude_dirsextra_compiler_argsf2py_optionsextra_f77_compile_argsextra_f90_compile_args。有关参数的更多信息,请参见.add_extension()方法。

config.have_f77c() — 如果 Fortran 77 编译器可用,则返回 True(即:简单的 Fortran 77 代码编译成功)。

config.have_f90c() — 如果 Fortran 90 编译器可用,则返回 True(即:简单的 Fortran 90 代码编译成功)。

config.get_version() — 返回当前包的版本字符串,如果无法检测到版本信息,则返回None。该方法扫描文件__version__.py<packagename>_version.pyversion.py__svn_version__.py查找字符串变量version__version__<packagename>_version

config.make_svn_version_py() — 在data_files列表中追加一个数据函数,该函数将生成__svn_version__.py文件到当前包目录。该文件将在 Python 退出时从源目录中删除。

config.get_build_temp_dir() — 返回临时目录的路径。这是构建临时文件的位置。

config.get_distribution() — 返回 distutils Distribution实例。

config.get_config_cmd() — 返回numpy.distutils配置命令实例。

config.get_info(*names)

使用模板转换.src文件

NumPy distutils 支持自动转换以.src结尾的源文件。该功能可用于保留在块之间仅需进行简单更改的非常相似代码块。在设置的构建阶段,如果遇到名为<somefile>.src的模板文件,则将从模板构造一个新文件<somefile>并将其放置在构建目录中以供使用。支持两种模板转换形式。第一种形式用于以扩展名(f、f90、f95、f77、for、ftn、pyf)结尾的文件。第二种形式用于所有其他情况。

Fortran 文件

此模板转换器将根据‘<…>’中的规则,复制文件中所有函数子例程块的名称中包含‘<…>’的块。‘<…>’中以逗号分隔的单词数确定块重复的次数。这些单词表示每个块中应该用重复规则‘<…>’替换的内容。块中的所有重复规则必须包含相同数量的逗号分隔的单词,表示该块应重复的次数。如果重复规则中的单词需要逗号、左箭头或右箭头,则用反斜杠‘ '’在前面加上它。如果重复规则中的单词与‘ <index>’匹配,则它将被替换为相同重复规范中索引号-th 单词。重复规则有两种形式:命名和缩写。

命名重复规则

当同一组重复必须在块中多次使用时,命名重复规则非常有用。它使用<rule1=item1, item2, item3,…, itemN>来指定,其中 N 是应重复块的次数。在每次重复块时,整个表达式‘<…>’将首先替换为 item1,然后替换为 item2,依此类推,直到完成 N 次重复。一旦引入了一个命名重复规则,同一重复规则可以通过仅指定名称(即)在当前块中使用。

缩写重复规则

缩写重复规则看起来像<item1, item2, item3, …, itemN>。该规则指定整个表达式‘<…>’应首先替换为 item1,然后替换为 item2,依此类推,直到完成 N 次重复。

预定义名称

下面列出了可用的预定义命名重复规则:

  • <prefix=s,d,c,z>
  • <_c=s,d,c,z>
  • <_t=实数, 双精度, 复数, 双精度复数>
  • <ftype=实数, 双精度, 复数, 双精度复数>
  • <ctype=浮点数, 双精度, 复数, 双精度复数>
  • <ftypereal=浮点数, 双精度, \0, \1>
  • <ctypereal=浮点数, 双精度, \0, \1>
命名重复规则

当同一组重复必须在块中多次使用时,命名重复规则非常有用。它使用<rule1=item1, item2, item3,…, itemN>来指定,其中 N 是应重复块的次数。在每次重复块时,整个表达式‘<…>’将首先替换为 item1,然后替换为 item2,依此类推,直到完成 N 次重复。一旦引入了一个命名重复规则,同一重复规则可以通过仅指定名称(即)在当前块中使用。

缩写重复规则

缩写重复规则看起来像<item1, item2, item3, …, itemN>。该规则指定整个表达式‘<…>’应首先替换为 item1,然后替换为 item2,依此类推,直到完成 N 次重复。

预定义名称

下面列出了��用的预定义命名重复规则:

  • <prefix=s,d,c,z>
  • <_c=s,d,c,z>
  • <_t=实数, 双精度, 复数, 双精度复数>
  • <ftype=实数, 双精度, 复数, 双精度复数>
  • <ctype=float, double, complex_float, complex_double>
  • <ftypereal=float, double precision, \0, \1>
  • <ctypereal=float, double, \0, \1>
其他文件

非 Fortran 文件使用单独的语法来定义应使用类似于 Fortran 特定重复的命名重复规则的模板块。

NumPy Distutils 预处理用自定义模板语言编写的 C 源文件(扩展名:.c.src)以生成 C 代码。@符号用于包装宏风格变量,以实现描述(例如)一组数据类型的字符串替换机制。

模板语言块由/**begin repeat/**end repeat**/行界定,也可以使用连续编号的界定行进行嵌套,如/**begin repeat1/**end repeat1**/

  1. 单独一行上的/**begin repeat标志着应重复的段的开始。
  2. 使用#name=item1, item2, item3, ..., itemN#定义命名变量扩展,并放置在连续行上。这些变量将在每个重复块中与相应的单词替换。同一重复块中的所有命名变量必须定义相同数量的单词。
  3. 在指定命名变量的重复规则时,item*N表示item, item, ..., item重复 N 次。此外,结合*N的括号可以用于分组多个应重复的项目。因此,#name=(item1, item2)*4#等同于#name=item1, item2, item1, item2, item1, item2, item1, item2#
  4. 单独一行上的*/标志着变量扩展命名的结束。接下来的一行将是使用命名规则重复的第一行。
  5. 在应重复的块内,要扩展的变量被指定为@name@
  6. 单独一行上的/**end repeat**/标记着前一行作为应重复的块的最后一行。
  7. NumPy C 源代码中的循环可能有一个@TYPE@变量,用于字符串替换,它经过预处理后将成为几个其他相同的循环,带有诸如INTLONGUINTULONG等多个字符串。因此,@TYPE@样式的语法通过模仿具有通用类型支持的语言来减少代码重复和维护负担。

以上规则在以下模板源示例中可能更清晰:

代码语言:javascript
复制
 1  /* TIMEDELTA to non-float types */
 2
 3  /**begin repeat 4 *
 5 * #TOTYPE = BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG,
 6 *           LONGLONG, ULONGLONG, DATETIME,
 7 *           TIMEDELTA#
 8 * #totype = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
 9 *           npy_long, npy_ulong, npy_longlong, npy_ulonglong,
10 *           npy_datetime, npy_timedelta#
11 */
12
13  /**begin repeat1 14 *
15 * #FROMTYPE = TIMEDELTA#
16 * #fromtype = npy_timedelta#
17 */
18  static  void
19  @FROMTYPE@_to_@TOTYPE@(void *input, void *output, npy_intp n,
20  void  *NPY_UNUSED(aip),  void  *NPY_UNUSED(aop))
21  {
22  const  @fromtype@ *ip = input;
23  @totype@ *op = output;
24
25  while  (n--)  {
26  *op++  =  (@totype@)*ip++;
27  }
28  }
29  /**end repeat1**/ 30
31  /**end repeat**/ 

通用类型化 C 源文件的预处理(无论是在 NumPy 本身中还是在使用 NumPy Distutils 的任何第三方包中)由conv_template.py执行。在构建过程中由这些模块生成的特定类型的 C 文件(扩展名:.c)可供编译。这种通用类型化也适用于 C 头文件(预处理以生成.h文件)。

numpy.distutils.misc_util中的有用函数
  • get_numpy_include_dirs() — 返回 NumPy 基本包含目录的列表。NumPy 基本包含目录包含诸如numpy/arrayobject.hnumpy/funcobject.h等头文件。对于已安装的 NumPy,返回的列表长度为 1,但构建 NumPy 时,列表可能包含更多目录,例如,由numpy/base/setup.py生成并由numpy头文件使用的config.h文件的路径。
  • append_path(prefix,path) — 将path智能添加到prefix上。
  • gpaths(paths, local_path='') — 对路径应用 glob,并在需要时在前面添加local_path
  • njoin(*path) — 将路径名组件联接在一起,将以/分隔的路径转换为os.sep分隔的路径,并解析路径中的...。例如njoin('a',['b','./c'],'..','g') -> os.path.join('a','b','g')
  • minrelpath(path) — 解析path中的点。
  • rel_path(path, parent_path) — 返回相对于parent_pathpath
  • def get_cmd(cmdname,_cache={}) — 返回numpy.distutils命令实例。
  • all_strings(lst)
  • has_f_sources(sources)
  • has_cxx_sources(sources)
  • filter_sources(sources) — 返回c_sources, cxx_sources, f_sources, fmodule_sources
  • get_dependencies(sources)
  • is_local_src_dir(directory)
  • get_ext_source_files(ext)
  • get_script_files(scripts)
  • get_lib_source_files(lib)
  • get_data_files(data)
  • dot_join(*args) — 用点联接非零参数。
  • get_frame(level=0) — 根据指定的 level 从调用栈返回 frame 对象。
  • cyg2win32(path)
  • mingw32() — 在使用 mingw32 环境时返回True
  • terminal_has_colors(), red_text(s), green_text(s), yellow_text(s), blue_text(s), cyan_text(s)
  • get_path(mod_name,parent_path=None) — 在给定的 parent_path 下返回模块的路径。还处理__main____builtin__模块。
  • allpath(name) — 将name中的/替换为os.sep
  • cxx_ext_match, fortran_ext_match, f90_ext_match, f90_module_name_match
numpy.distutils.system_info模块
  • get_info(name,notfound_action=0)
  • combine_paths(*args,**kws)
  • show_all()
numpy.distutils.cpuinfo模块
  • cpuinfo
numpy.distutils.log模块
  • set_verbosity(v)
numpy.distutils.exec_command模块
  • get_pythonexe()
  • find_executable(exe, path=None)
  • exec_command( command, execute_in='', use_shell=None, use_tee=None, **env )

__init__.py文件

一个典型的 SciPy __init__.py的头部是:

代码语言:javascript
复制
"""
Package docstring, typically with a brief description and function listing.
"""

# import functions into module namespace
from .subpackage import *
...

__all__ = [s for s in dir() if not s.startswith('_')]

from numpy.testing import Tester
test = Tester().test
bench = Tester().bench 

NumPy Distutils 的额外功能

在 setup.py 脚本中为库指定 config_fc 选项

可以在 setup.py 脚本中指定 config_fc 选项。例如,使用

config.add_library(‘library’, sources=[…], config_fc={‘noopt’😦file,1)})

将编译library源码时不使用优化标志。

建议仅以与编译器无关的方式指定那些 config_fc 选项

从源代码获取额外的 Fortran 77 编译器选项

一些旧的 Fortran 代码需要特殊的编译器选项才能正常工作。为了指定每个源文件的编译器选项,numpy.distutils Fortran 编译器寻找以下模式:

代码语言:javascript
复制
CF77FLAGS(<fcompiler type>) = <fcompiler f77flags> 

在源文件的前 20 行中,并使用指定类型的 fcompiler 的f77flags(第一个字符C是可选的)。

TODO:这个功能也可以轻松扩展到 Fortran 90 代码上。如果您需要这样的功能,请告诉我们。

在 setup.py 脚本中为库指定 config_fc 选项。

可以在 setup.py 脚本中指定 config_fc 选项。例如,使用

config.add_library(‘library’, sources=[…], config_fc={‘noopt’😦file,1)})

编译library源码时不使用优化标志。

建议仅指定那些与编译器无关的 config_fc 选项。

从源码中获取额外的 Fortran 77 编译器选项。

一些旧的 Fortran 代码需要特殊的编译器选项才能正常工作。为了指定每个源文件的编译器选项,numpy.distutils Fortran 编译器寻找以下模式:

代码语言:javascript
复制
CF77FLAGS(<fcompiler type>) = <fcompiler f77flags> 

在源文件的前 20 行中,并使用指定类型的 fcompiler 的f77flags(第一个字符C是可选的)。

TODO:这个功能也可以轻松扩展到 Fortran 90 代码上。如果您需要这样的功能,请告诉我们。

numpy.distutils 的状态和迁移建议

原文:numpy.org/doc/1.26/reference/distutils_status_migration.html

numpy.distutils 已在 NumPy 1.23.0 中被弃用。它将在 Python 3.12 中被移除;对于 Python <= 3.11,它将在 Python 3.12 发布后的 2 年内不会被移除(2025 年 10 月)。

警告

numpy.distutils 仅与 setuptools < 60.0 进行了测试,更新的版本可能会出现问题。有关详细信息,请参见 numpy.distutils 与 setuptools 的交互。

迁移建议

有几个很好的选项可供迁移。假设您的软件包中有编译代码(如果没有,您有几个很好的选项,例如 Poetry、Hatch 或 PDM 提供的构建后端),并且您希望使用一个设计良好、现代且可靠的构建系统,我们建议使用:

  1. Meson,以及 meson-python 构建后端
  2. CMake,以及 scikit-build-core 构建后端

如果您的需求不高(只有简单的 Cython/C 扩展;不需要 Fortran、BLAS/LAPACK、嵌套的 setup.py 文件或 numpy.distutils 的其他功能),并且迄今为止对 numpy.distutils 感到满意,您也可以考虑切换到 setuptools。请注意,numpy.distutils 的大多数功能不太可能被移植到 setuptools

迁移到 Meson

SciPy 在其 1.9.0 版本中已经转向使用 Meson 和 meson-python。在此过程中,解决了 Meson 的 Python 支持和与 numpy.distutils 功能对齐的剩余问题。注意:对齐意味着一个大的超集(因为 Meson 是一个很好的通用构建系统);只有一些 BLAS/LAPACK 库选择的细微差别是缺失的。SciPy 几乎使用了 numpy.distutils 提供的所有功能,因此如果 SciPy 成功地使用 Meson 作为构建系统发布了一个版本,那么应该没有障碍可以阻止迁移,SciPy 将成为其他正在迁移的软件包的良好参考。有关 SciPy 迁移的更多详细信息,请参见:

NumPy 将在 1.26 版本中迁移到 Meson。

迁移到 CMake / scikit-build

下一代 scikit-build 称为 scikit-build-core。在旧的 scikit-build 使用 setuptools 作为底层时,重写不再使用。与 Meson 一样,CMake 是一个很好的通用构建系统。

迁移到 setuptools

对于仅因历史原因而使用numpy.distutils的项目,并且实际上没有使用setuptools也支持的功能,迁移到setuptools很可能是成本最低的解决方案。为评估这一点,有一些numpy.distutils功能 setuptools中存在:

  • 嵌套的setup.py文件
  • Fortran 构建支持
  • BLAS / LAPACK 库支持(OpenBLAS、MKL、ATLAS、Netlib LAPACK / BLAS、BLIS、64 位 ILP 接口等)
  • 对其他一些科学库的支持,如 FFTW 和 UMFPACK
  • 更好的 MinGW 支持
  • 每个编译器的构建标志自定义(例如* -O3 SSE2*标志是默认的)
  • 一个简单的用户构建配置系统,请查看site.cfg.example
  • SIMD 内在支持

最广泛使用的功能是嵌套的setup.py文件。该功能可能将来可能仍然被移植到setuptools中(但需要一个志愿者,见gh-18588了解状态)。只使用该功能的项目在此之后可以迁移到setuptools。如果一个项目只使用了几个setup.py文件,将这些文件的所有内容聚合到一个单独的setup.py文件中,然后迁移到setuptools可能是有意义的。这涉及放弃所有Configuration实例,并改用Extension。例如:

代码语言:javascript
复制
from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[
          Extension('foopkg.foo', ['foo.c']),
          Extension('barpkg.bar', ['bar.c']),
          ],
      ) 

有关更多细节,请参阅setuptools 文档

##numpy.distutilssetuptools的互动

建议使用setuptools < 60.0。更新的版本可能有效,但不能保证。原因是setuptools 60.0 启用了distutils的供应商副本,其中包含一些影响numpy.distutils某些功能的向后不兼容更改。

如果您只使用简单的 Cython 或 C 扩展并最小限度地使用numpy.distutils功能,超出嵌套的setup.py文件(它最流行的特性,请参阅Configuration),那么最新的setuptools可能会继续运作正常。如果出现问题,您还可以尝试SETUPTOOLS_USE_DISTUTILS=stdlib来避免setuptools中不兼容的更改。

无论您做什么,建议在pyproject.toml中对setuptools的构建需求设置一个上限,以避免未来的破坏 - 请参见对下游包作者的建议。

迁移建议

有几种可供迁移的构建系统选择。假设您的软件包中有编译代码(如果没有,您有几个良好的选择,例如 Poetry、Hatch 或 PDM 提供的构建后端),并且您希望使用一个设计良好、现代化和可靠的构建系统,我们建议:

  1. Mesonmeson-python构建后端
  2. CMakescikit-build-core构建后端

如果您只需要简单的 Cython/C 扩展(不需要 Fortran,BLAS/LAPACK,嵌套的setup.py文件或其他numpy.distutils的功能),并且迄今为止对numpy.distutils感到满意,您也可以考虑切换到setuptools。请注意,大多数numpy.distutils的功能不太可能被迁移到setuptools

迁移至 Meson

SciPy 在其 1.9.0 版本中已经迁移到了 Meson 和 meson-python。在此过程中,已解决了 Meson 的 Python 支持以及与numpy.distutils功能平等的剩余问题。注意:平等意味着一个大的超集(因为 Meson 是一个很好的通用构建系统);只有一些 BLAS/LAPACK 库选择上的小问题缺失。SciPy 几乎使用了numpy.distutils提供的所有功能,因此如果 SciPy 成功发布了使用 Meson 作为构建系统的版本,那么应该没有任何阻碍可以迁移,SciPy 将成为其他正在迁移的软件包的良好参考。有关 SciPy 迁移的更多详细信息,请参见:

NumPy 将在 1.26 版本中迁移到 Meson。

迁移到 CMake / scikit-build

下一代 scikit-build 称为scikit-build-core。旧版的scikit-build使用了setuptools作为底层,但重写并没有。与 Meson 一样,CMake 是一个很好的通用构建系统。

迁移到setuptools

对于仅出于历史原因使用numpy.distutils的项目,并且实际上没有使用setuptools也支持的功能,移至setuptools很可能是耗费最少努力的解决方案。为了评估,这里是setuptools没有存在的numpy.distutils功能:

  • 嵌套的setup.py文件
  • Fortran 构建支持
  • BLAS/LAPACK 库支持(OpenBLAS,MKL,ATLAS,Netlib LAPACK/BLAS,BLIS,64 位 ILP 接口等)
  • 支持其他几个科学库,如 FFTW 和 UMFPACK
  • 更好的 MinGW 支持
  • 每个编译器的构建标志定制(例如,默认为* -O3 SSE2 *标志)
  • 一个简单的用户构建配置系统,请参阅site.cfg.example
  • SIMD 指令集支持

最广泛使用的功能是嵌套的setup.py文件。这个功能可能将来仍然被移植到setuptools中(需要一个志愿者,参见gh-18588了解状态)。只使用该功能的项目在完成后可以转移到setuptools。如果一个项目只使用了几个setup.py文件,将这些文件的所有内容聚合到一个单独的setup.py文件中,然后转移到setuptools也是有意义的。这涉及放弃所有Configuration实例,并改用Extension。例如:

代码语言:javascript
复制
from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[
          Extension('foopkg.foo', ['foo.c']),
          Extension('barpkg.bar', ['bar.c']),
          ],
      ) 

更多详细信息,请参见setuptools 文档

转移到 Meson。

SciPy 已经在其 1.9.0 版本中迁移到 Meson 和 meson-python。在此过程中,解决了 Meson 的 Python 支持和与numpy.distutils功能平衡的剩余问题。注意:平衡意味着一个大的超集(因为 Meson 是一个很好的通用构建系统);只有一些 BLAS/LAPACK 库选择的细微差别缺失。SciPy 几乎使用了numpy.distutils提供的所有功能,因此如果 SciPy 成功使用 Meson 作为构建系统发布了一个版本,那么应该没有障碍可以迁移,SciPy 将成为其他正在迁移的软件包的良好参考。有关 SciPy 迁移的更多详细信息,请参见:

NumPy 将在 1.26 版本中迁移到 Meson。

转移到 CMake / scikit-build。

下一代 scikit-build 被称为scikit-build-core。旧的scikit-build使用setuptools作为底层,而重写则不是。与 Meson 一样,CMake 是一个很好的通用构建系统。

转移到setuptools

对于仅出于历史原因使用numpy.distutils的项目,并且实际上没有使用setuptools支持的功能,转移到setuptools可能是付出最少努力的解决方案。为了评估这一点,有一些numpy.distutils功能存在于setuptools中:

  • 嵌套的setup.py文件。
  • Fortran 构建支持。
  • BLAS/LAPACK 库支持(OpenBLAS、MKL、ATLAS、Netlib LAPACK/BLAS、BLIS、64 位 ILP 接口等)。
  • 支持其他几个科学库,如 FFTW 和 UMFPACK。
  • 更好的 MinGW 支持。
  • 每个编译器的构建标志自定义(例如,默认为*-O3SSE2*标志)
  • 一个简单的用户构建配置系统,请参见site.cfg.example
  • SIMD 指令支持。

最广泛使用的功能是嵌套的setup.py文件。这个功能可能在将来仍然会被移植到setuptools中(不过需要有志愿者,参见gh-18588了解状态)。只使用该功能的项目在完成后可以转移到setuptools。如果一个项目只使用了几个setup.py文件,将这些文件的所有内容聚合到一个单独的setup.py文件中,然后转移到setuptools也是有意义的。这涉及放弃所有的Configuration实例,并使用Extension代替。例如:

代码语言:javascript
复制
from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[
          Extension('foopkg.foo', ['foo.c']),
          Extension('barpkg.bar', ['bar.c']),
          ],
      ) 

更多详情,请参阅setuptools 文档

numpy.distutilssetuptools的交互

建议使用setuptools < 60.0。更新的版本可能会工作,但不能保证。原因是setuptools 60.0 启用了distutils的一个供应商副本,其中包含影响numpy.distutils某些功能的不兼容更改。

如果你只是简单地使用 Cython 或 C 扩展,并且最多只是在嵌套的setup.py文件之外使用了少量numpy.distutils功能(它最受欢迎的功能,请参见Configuration),那么最新的setuptools可能会继续工作。如果出现问题,你也可以尝试SETUPTOOLS_USE_DISTUTILS=stdlib来避免setuptools中的不兼容更改。

无论你做什么,建议在pyproject.toml中对你的setuptools构建需求设置一个上限,以避免未来的破坏 - 参见对下游包作者的建议。

NumPy C-API

原文:numpy.org/doc/1.26/reference/c-api/index.html

当心那些不愿意去理会细节的人。— *威廉·菲瑟(William Feather, Sr.)*真相在那里。— 克里斯·卡特(Chris Carter),《X 档案》

NumPy 提供了一个 C-API,使用户能够扩展系统并访问数组对象以在其他程序中使用。真正理解 C-API 的最佳方式是阅读源代码。然而,如果你不熟悉(C)源代码,这一开始可能会让人望而生畏。请放心,随着练习,这个任务会变得更容易,你可能会惊讶于理解 C 代码的简单程度。即使你认为自己无法从头编写 C 代码,理解和修改已经编写好的源代码要比从零开始编写要容易得多。

Python 扩展特别容易理解,因为它们都具有非常相似的结构。诚然,NumPy 不是 Python 的一个琐碎扩展,可能需要更多的探索才能理解。这尤其是因为代码生成技术简化了非常相似的代码的维护,但对初学者来说可能会使代码稍微难以阅读。不过,稍加坚持,你就能理解这些代码。我希望这份关于 C-API 的指南能够帮助你熟悉使用 NumPy 进行编译级工作的过程,以便从你的代码中挤出最后一丝必要的速度。

  • Python 类型和 C 结构
    • 定义的新 Python 类型
    • 其他 C 结构
  • 系统配置
    • 数据类型大小
    • 平台信息
    • 编译器指令
  • 数据类型 API
    • 枚举类型
    • 定义
    • C 类型名称
    • Printf 格式化
  • 数组 API
    • 数组结构和数据访问
    • 创建数组
    • 处理类型
    • 数组标志
    • 数组方法替代 API
    • 函数
    • 具有对象语义的辅助数据
    • 数组迭代器
    • 广播(多迭代器)
    • 邻域迭代器
    • 数组映射
    • 数组标量
    • 数据类型描述符
    • 转换工具
    • 杂项
  • 数组迭代器 API
    • 数组迭代器
    • 迭代示例
    • 多次迭代示例
    • 多索引跟踪示例
    • 迭代器数据类型
    • 构造和销毁
    • 迭代函数
    • 从以前的 NumPy 迭代器转换
  • UFunc API
    • 常量
    • 类型
    • 函数
    • 通用函数
    • 导入 API
  • 广义通用函数 API
    • 定义
    • 签名的详细信息
    • 用于实现基本函数的 C API
  • NumPy 核心库
    • NumPy 核心数学库
  • C API 废弃
    • 背景
    • 废弃机制 NPY_NO_DEPRECATED_API
  • NumPy 中的内存管理
    • 历史概览
    • NumPy 中可配置的内存例程(NEP 49)
    • 如果没有设置策略,则释放内存时会发生什么
    • 使用 np.lib.tracemalloc_domain 进行内存跟踪的示例

Python 类型和 C 结构

原文:numpy.org/doc/1.26/reference/c-api/types-and-structures.html

几种新类型在 C 代码中定义。其中大多数可以从 Python 中访问,但由于使用受限,有些则没有暴露出来。每个新的 Python 类型都有一个关联的PyObject*,其内部结构包括指向“方法表”的指针,定义了新对象在 Python 中的行为。在 C 代码中接收到 Python 对象时,始终会得到一个指向PyObject 结构的指针。因为 PyObject 结构非常通用,仅定义了 PyObject_HEAD,因此本身并不是很有趣。但是,不同类型的对象在PyObject_HEAD之后包含更多细节(但你必须将其转换为正确的类型才能访问它们 - 或者使用访问器函数或宏)。

定义了新的 Python 类型

Python 类型在 C 语言中等效于 Python 中的类。通过构建新的 Python 类型,可以为 Python 提供一个新的对象。ndarray 对象就是在 C 中定义的一个新类型的例子。通过两个基本步骤在 C 中定义新类型:

  1. 创建一个 C 结构(通常命名为 Py{Name}Object),它与 PyObject 结构本身二进制兼容,但包含了特定对象需要的额外信息;
  2. 使用指针指向实现所需行为的函数,将PyTypeObject表(由PyObject 结构的 ob_type 成员指向)填充。

不再使用定义 Python 类的特殊方法名,而是使用指向实现所需结果的函数的“函数表”。自从 Python 2.2 开始,PyTypeObject 本身变得动态,允许从其他 C 类型“子类型化” C 类型,并在 Python 中派生子类。子类型继承其父类的属性和方法。

有两种主要的新类型:ndarray( PyArray_Type )和 ufunc( PyUFunc_Type )。其他类型起着支持作用:PyArrayIter_TypePyArrayMultiIter_TypePyArrayDescr_TypePyArrayIter_Type 是用于 ndarray 的平面迭代器的类型(获取 flat 属性时返回的对象)。PyArrayMultiIter_Type 是在调用 broadcast () 时返回的对象的类型。它处理对嵌套序列集合的迭代和广播。此外,PyArrayDescr_Type 是描述数据的数据类型描述符类型,其实例描述数据。最后,有 21 种新的标量数组类型,它们是与数组可用的每种基本数据类型对应的新的 Python 标量。另外还有 10 种其他类型是占位符,允许数组标量适应实际 Python 类型的层次结构。

PyArray_Type 和 PyArrayObject
代码语言:javascript
复制
PyArray_Type

ndarray 的 Python 类型是 PyArray_Type。在 C 中,每个 ndarray 都是指向 PyArrayObject 结构的指针。此结构的 ob_type 成员包含指向 PyArray_Type 类型对象的指针。

代码语言:javascript
复制
type PyArrayObject
代码语言:javascript
复制
type NPY_AO

PyArrayObject C 结构包含数组的所有必需信息。所有 ndarray(及其子类)的实例都将具有此结构。为了未来的兼容性,应该通常使用提供的宏来访问这些结构成员。如果需要更短的名称,那么可以使用已弃用的 NPY_AO,它被定义为等同于 PyArrayObject。直接访问结构字段已被弃用。请改用 PyArray_*(arr) 形式。截至 NumPy 1.20,此结构的大小不被视为 NumPy ABI 的一部分(请参见成员列表末尾的注释)。

代码语言:javascript
复制
typedef  struct  PyArrayObject  {
  PyObject_HEAD
  char  *data;
  int  nd;
  npy_intp  *dimensions;
  npy_intp  *strides;
  PyObject  *base;
  PyArray_Descr  *descr;
  int  flags;
  PyObject  *weakreflist;
  /* version dependent private members */
}  PyArrayObject; 
代码语言:javascript
复制
PyObject_HEAD

这是所有 Python 对象所需的。它至少包含一个引用计数成员( ob_refcnt )和一个指向类型对象的指针( ob_type )。(如果 Python 是使用特殊选项编译的,还可能存在其他元素,请参阅 Python 源树中的 Include/object.h 了解更多信息)。ob_type 成员指向 Python 类型对象。

代码语言:javascript
复制
char *data

通过 PyArray_DATA 可访问,此数据成员是数组的第一个元素的指针。这个指针可以(通常应该)重新转换为数组的数据类型。

代码语言:javascript
复制
int nd

一个整数,提供此数组的维数。当 nd 为 0 时,有时称为秩-0 数组。这种数组具有未定义的维度和步幅,无法访问。宏PyArray_NDIM定义在ndarraytypes.h指向这个数据成员。NPY_MAXDIMS 是任何数组的最大维数。

代码语言:javascript
复制
*dimensions

一个整数数组,为每个维度提供该维度中的形状,只要 nd (\geq) 1。这个整数总是足够大,能够在平台上保存一个指针,所以维度大小仅受内存限制。PyArray_DIMS 是与这个数据成员相关联的宏。

代码语言:javascript
复制
*strides

一个整数数组,为每个维度提供必须跳过的字节数,以到达该维度中的下一个元素。与宏PyArray_STRIDES相关联。

代码语言:javascript
复制
*base

PyArray_BASE指向,这个成员用于保存与这个数组相关的另一个 Python 对象的指针。有两个用例:

  • 如果这个数组没有拥有自己的内存,那么 base 指向拥有它的 Python 对象(也许是另一个数组对象)。
  • 如果这个数组设置了NPY_ARRAY_WRITEBACKIFCOPY标志,那么这个数组是一个“不良”数组的工作副本。

当调用PyArray_ResolveWritebackIfCopy时,base 指向的数组将使用这个数组的内容更新。

代码语言:javascript
复制
*descr

指向数据类型描述符对象的指针(见下文)。数据类型描述符对象是新建的内置类型的实例,它允许对内存进行通用描述。对每个支持的数据类型都存在一个描述符结构。这个描述符结构包含有关类型的有用信息,以及一个指向实现特定功能的函数指针表的指针。顾名思义,它与宏PyArray_DESCR相关联。

代码语言:javascript
复制
int flags

由宏PyArray_FLAGS指向,这个数据成员表示标志,指示数据指针指向的内存应如何解释。可能的标志是NPY_ARRAY_C_CONTIGUOUSNPY_ARRAY_F_CONTIGUOUSNPY_ARRAY_OWNDATANPY_ARRAY_ALIGNEDNPY_ARRAY_WRITEABLENPY_ARRAY_WRITEBACKIFCOPY

代码语言:javascript
复制
*weakreflist

这个成员允许数组对象具有弱引用(使用 weakref 模块)。

注意

其他成员被视为私有和与版本有关。如果结构的大小对您的代码很重要,必须特别小心。当这一点相关时的一种可能的用例是在 C 中进行子类化。如果您的代码依赖于 sizeof(PyArrayObject) 的大小是不变的,您在导入时必须添加以下检查:

代码语言:javascript
复制
if  (sizeof(PyArrayObject)  <  PyArray_Type.tp_basicsize)  {
  PyErr_SetString(PyExc_ImportError,
  "Binary incompatibility with NumPy, must recompile/update X.");
  return  NULL;
} 

为了确保您的代码不必为特定的 NumPy 版本进行编译,您可以添加一个常数,留出 NumPy 变化的空间。可确保与将来任何 NumPy 版本兼容的解决方案需要使用运行时计算偏移和分配大小。

PyArrayDescr_Type 和 PyArray_Descr
代码语言:javascript
复制
PyArrayDescr_Type

PyArrayDescr_Type 是用于描述数组所包含的字节应如何解释的数据类型描述对象的内置类型。内置数据类型有 21 个静态定义的 PyArray_Descr 对象。虽然这些对象参与引用计数,但它们的引用计数永远不应该达到零。还有一个动态的用户自定义 PyArray_Descr 对象表也会被维护。一旦数据类型描述对象被“注册”,它就不应该被释放。函数 PyArray_DescrFromType (…) 可以用来从一个枚举类型编号(内置或用户自定义)中检索出一个 PyArray_Descr 对象。

代码语言:javascript
复制
type PyArray_Descr

PyArray_Descr 结构位于 PyArrayDescr_Type 的核心。虽然这里描述了它,但它应被视为 NumPy 的内部部分,并通过 PyArrayDescr_*PyDataType* 函数和宏进行操作。这个结构的大小会随着 NumPy 的版本变化而变化。为确保兼容性:

  • 永远不要声明结构的非指针实例
  • 永远不要执行指针算术运算
  • 永远不要使用 sizeof(PyArray_Descr)

它具有以下结构:

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  PyTypeObject  *typeobj;
  char  kind;
  char  type;
  char  byteorder;
  char  flags;
  int  type_num;
  int  elsize;
  int  alignment;
  PyArray_ArrayDescr  *subarray;
  PyObject  *fields;
  PyObject  *names;
  PyArray_ArrFuncs  *f;
  PyObject  *metadata;
  NpyAuxData  *c_metadata;
  npy_hash_t  hash;
}  PyArray_Descr; 
代码语言:javascript
复制
*typeobj

指向该数组元素对应的 Python 类型的类型对象的指针。对于内置类型,这将指向对应的 array scalar。对于用户定义类型,这应该指向用户定义的类型对象。这个类型对象可以继承自数组标量,也可以不继承。如果它不继承自数组标量,那么flags 成员中应该设置 NPY_USE_GETITEMNPY_USE_SETITEM 标志。

代码语言:javascript
复制
char kind

表示数组种类的字符代码(使用数组接口类型字符串表示)。‘b’ 表示布尔型,‘i’ 表示有符号整数,‘u’ 表示无符号整数,‘f’ 表示浮点型,‘c’ 表示复数浮点型,‘S’ 表示 8 位零终结字节,‘U’ 表示 32 位/字符 Unicode 字符串,‘V’ 表示任意类型。

代码语言:javascript
复制
char type

指示数据类型的传统字符代码。

代码语言:javascript
复制
char byteorder

表示字节顺序的字符:‘>’(大端),‘<’(小端),‘=’(本地),‘|’(不相关,忽略)。所有内置数据类型的字节顺序为‘=’。

代码语言:javascript
复制
char flags

决定数据类型是否具有对象数组行为的数据类型位标志。此成员中的每个位都是一个标志,其命名为:

  • NPY_ITEM_REFCOUNT
  • NPY_ITEM_HASOBJECT
  • NPY_LIST_PICKLE
  • NPY_ITEM_IS_POINTER
  • NPY_NEEDS_INIT
  • NPY_NEEDS_PYAPI
  • NPY_USE_GETITEM
  • NPY_USE_SETITEM
  • NPY_FROM_FIELDS
  • NPY_OBJECT_DTYPE_FLAGS
代码语言:javascript
复制
int type_num

唯一标识数据类型的数字。对于新的数据类型,当数据类型注册时会分配此数字。

代码语言:javascript
复制
int elsize

对于始终大小相同的数据类型(例如 long),这表示数据类型的大小。对于灵活的数据类型,其中不同的数组可以具有不同的元素大小,这应为 0。

代码语言:javascript
复制
int alignment

提供此数据类型的对齐信息的数字。具体来说,它显示编译器在从 2 个元素结构的开始(其第一个元素是一个 char)放置此类型的项目的距离:offsetof(struct {char c; type v;}, v)

代码语言:javascript
复制
*subarray

如果此为非 NULL,则此数据类型描述符是另一个数据类型描述符的 C 风格连续数组。换句话说,此描述符描述的每个元素实际上是另一个基本描述符的数组。如果此为非 NULL,则字段成员应为 NULL(但是基本描述符的字段成员可以为非 NULL)。

代码语言:javascript
复制
type PyArray_ArrayDescr
代码语言:javascript
复制
typedef  struct  {
  PyArray_Descr  *base;
  PyObject  *shape;
}  PyArray_ArrayDescr; 
代码语言:javascript
复制
*base

基本类型的数据类型描述符对象。

代码语言:javascript
复制
*shape

子数组的形状(始终为 C 风格连续)作为 Python 元组。

代码语言:javascript
复制
*fields

如果此为非空,则此数据类型描述符具有由 Python 字典描述的字段,其键是名称(如果给定也是标题),其值是描述字段的元组。请注意,数据类型描述符始终描述一组固定长度的字节。字段是总的、固定长度集合的命名子区域。字段由另一个数据类型描述符和字节偏移量组成的元组描述。可选地,元组可能包含通常为 Python 字符串的标题。这些元组根据名称(如果给定还有标题)放置在此字典中。

代码语言:javascript
复制
*names

字段名称的有序元组。如果未定义字段,则为 NULL。

代码语言:javascript
复制
*f

指向一个包含类型需要实现内部特性的函数的结构体的指针。这些函数不同于后面描述的通用函数(ufuncs)。它们的签名可以任意变化。

代码语言:javascript
复制
*metadata

关于此数据类型的元数据。

代码语言:javascript
复制
*c_metadata

这些特定于特定 dtype 的 C 实现的元数据。增加于 NumPy 1.7.0。

代码语言:javascript
复制
type npy_hash_t
代码语言:javascript
复制
*hash

目前未使用。保留以用于在缓存哈希值中将来使用。

代码语言:javascript
复制
NPY_ITEM_REFCOUNT

表示此数据类型的项必须进行引用计数(使用Py_INCREFPy_DECREF)。

代码语言:javascript
复制
NPY_ITEM_HASOBJECT

等同于NPY_ITEM_REFCOUNT

代码语言:javascript
复制
NPY_LIST_PICKLE

表示必须将这种数据类型的数组在 pickling 之前转换为列表。

代码语言:javascript
复制
NPY_ITEM_IS_POINTER

表示该项是指向其他数据类型的指针。

代码语言:javascript
复制
NPY_NEEDS_INIT

表示必须在创建时初始化(设置为 0)此数据类型的内存。

代码语言:javascript
复制
NPY_NEEDS_PYAPI

表示在访问时此数据类型需要 Python C-API(因此如果需要数组访问,请不要放弃 GIL)。

代码语言:javascript
复制
NPY_USE_GETITEM

在数组访问时,使用f->getitem函数指针,而不是标准的转换为数组标量。如果没有定义与数据类型相匹配的数组标量,必须使用。

代码语言:javascript
复制
NPY_USE_SETITEM

当从数组标量创建 0 维数组时,使用f->setitem而不是标准的从数组标量复制。如果你没有定义与数据类型相匹配的数组标量,必须使用。

代码语言:javascript
复制
NPY_FROM_FIELDS

如果在数据类型的任何字段中设置了这些位,则从父数据类型继承这些位。目前(NPY_NEEDS_INIT | NPY_LIST_PICKLE | NPY_ITEM_REFCOUNT | NPY_NEEDS_PYAPI)。

代码语言:javascript
复制
NPY_OBJECT_DTYPE_FLAGS

为对象数据类型设置的位:(NPY_LIST_PICKLE | NPY_USE_GETITEM | NPY_ITEM_IS_POINTER | NPY_ITEM_REFCOUNT | NPY_NEEDS_INIT | NPY_NEEDS_PYAPI)。

代码语言:javascript
复制
int PyDataType_FLAGCHK( *dtype, int flags)

如果数据类型对象的所有给定标志都设置为真,则返回真。

代码语言:javascript
复制
int PyDataType_REFCHK( *dtype)

等同于PyDataType_FLAGCHKdtypeNPY_ITEM_REFCOUNT)。

代码语言:javascript
复制
type PyArray_ArrFuncs

实现内部特性的函数。并非必须为给定类型定义所有这些函数指针。必须定义的成员包括nonzerocopyswapcopyswapnsetitemgetitemcast。这默认假定为非 NULL,而NULL条目将导致程序崩溃。其他函数可以是 NULL,这只会导致该数据类型的功能减少。(此外,如果在注册用户定义的数据类型时nonzero函数为空,将使用默认函数填充nonzero函数)。

代码语言:javascript
复制
typedef  struct  {
  PyArray_VectorUnaryFunc  *cast[NPY_NTYPES];
  PyArray_GetItemFunc  *getitem;
  PyArray_SetItemFunc  *setitem;
  PyArray_CopySwapNFunc  *copyswapn;
  PyArray_CopySwapFunc  *copyswap;
  PyArray_CompareFunc  *compare;
  PyArray_ArgFunc  *argmax;
  PyArray_DotFunc  *dotfunc;
  PyArray_ScanFunc  *scanfunc;
  PyArray_FromStrFunc  *fromstr;
  PyArray_NonzeroFunc  *nonzero;
  PyArray_FillFunc  *fill;
  PyArray_FillWithScalarFunc  *fillwithscalar;
  PyArray_SortFunc  *sort[NPY_NSORTS];
  PyArray_ArgSortFunc  *argsort[NPY_NSORTS];
  PyObject  *castdict;
  PyArray_ScalarKindFunc  *scalarkind;
  int  **cancastscalarkindto;
  int  *cancastto;
  PyArray_FastClipFunc  *fastclip;  /* deprecated */
  PyArray_FastPutmaskFunc  *fastputmask;  /* deprecated */
  PyArray_FastTakeFunc  *fasttake;  /* deprecated */
  PyArray_ArgFunc  *argmin;
}  PyArray_ArrFuncs; 

描述函数指针时使用了行为良好段的概念。行为良好的段是指与数据类型对齐且符合本机字节顺序的段。nonzerocopyswapcopyswapngetitemsetitem 函数可以(必须)处理不规范的数组。其他函数则需要行为良好的内存段。

代码语言:javascript
复制
void cast(void *from, void *to, n, void *fromarr, void *toarr)

一个函数指针数组,用于将当前类型转换为所有其他内置类型。每个函数都将由 from 指向的连续、对齐且未交换的缓冲区转换为由 to 指向的连续、对齐且未交换的缓冲区。要转换的项数由 n 给出,并且参数 fromarrtoarr 被解释为灵活数组的 PyArrayObjects 以获取 itemsize 信息。

代码语言:javascript
复制
*getitem(void *data, void *arr)

一个函数指针,用于从由 data 指向的数组对象 arr 的单个元素返回标准 Python 对象。此函数必须能够正确处理“不规范”的(未对齐和/或交换的)数组。

代码语言:javascript
复制
int setitem( *item, void *data, void *arr)

一个函数指针,用于将 Python 对象 item 设置到由 data 指向的数组 arr 中的位置。此函数处理“不规范”的数组。如果成功,返回零,否则返回负一(并设置 Python 错误)。

代码语言:javascript
复制
void copyswapn(void *dest, dstride, void *src, sstride, n, int swap, void *arr)
代码语言:javascript
复制
void copyswap(void *dest, void *src, int swap, void *arr)

这些成员都是指向从 src 复制数据到 dest 并在需要时交换的函数的指针。仅当为灵活数组(NPY_STRINGNPY_UNICODENPY_VOID )时才使用 arr 的值(从 arr->descr->elsize 获取)。第二个函数复制单个值,而第一个函数则使用提供的步幅循环 n 值。这些函数可以处理不规范的 src 数据。如果 src 为 NULL,则不执行复制。如果 swap 为 0,则不执行字节交换。假设 destsrc 不重叠。如果它们重叠,则首先使用 memmove(…)再使用值为 NULL 的 src 执行 copyswap(n)

代码语言:javascript
复制
int compare(const void *d1, const void *d2, void *arr)

一个函数指针,用于比较由 d1d2 指向的数组 arr 的两个元素。此函数需要行为良好(对齐且未交换)的数组。如果 * d1 > * d2,返回值为 1;如果 * d1 == * d2,返回值为 0;如果 * d1 < * d2,返回值为 -1。数组对象 arr 用于检索灵活数组的 itemsize 和字段信息。

代码语言:javascript
复制
int argmax(void *data, n, *max_ind, void *arr)

一个函数指针,用于从由 data 指向的元素开始的 n 个元素中检索最大的索引。此函数要求内存段是连续且行为良好的。返回值始终为 0。最大元素的索引在 max_ind 中返回。

代码语言:javascript
复制
void dotfunc(void *ip1, is1, void *ip2, is2, void *op, n, void *arr)

一个指向将两个n长度的序列相乘,相加,并将结果放置到由op指向的arr元素中的函数的指针。序列的开始分别由ip1ip2指向。要获取每个序列中的下一个元素需要跳过is1is2 字节。此函数需要表现良好的(尽管不一定是连续的)内存。

代码语言:javascript
复制
int scanfunc(FILE *fd, void *ip, void *arr)

一个指向从文件描述符fd中扫描(类似于 scanf)相应类型的元素到由ip指向的数组内存中的函数的指针。假定数组表现良好。最后一个参数arr是要扫描的数组。返回成功分配的接收参数的数量(如果在分配第一个接收参数之前匹配失败,则可能为零),或者如果在分配第一个接收参数之前发生输入故障,则为 EOF。调用此函数时应该不持有 Python GIL,并且必须为错误报告抓取它。

代码语言:javascript
复制
int fromstr(char *str, void *ip, char **endptr, void *arr)

一个指向将str指向的字符串转换为相应类型的一个元素并将其放置到由ip指向的内存位置的函数的指针。转换完成后,*endptr指向字符串的其余部分。最后一个参数arr是 ip 指向的数组(需要用于变量大小数据类型)。成功返回 0,失败返回-1。需要一个表现良好的数组。调用此函数时应该不持有 Python GIL,并且必须为错误报告抓取它。

代码语言:javascript
复制
nonzero(void *data, void *arr)

一个指向如果data指向的arr的项为非零则返回 TRUE 的函数的指针。此函数可以处理行为不当的数组。

代码语言:javascript
复制
void fill(void *data, length, void *arr)

一个指向填充给定长度的连续数组数据的函数的指针。数组的前两个元素必须已经被填充。根据这两个值,将计算出一个增量,然后从第 3 个元素到最后的值将通过重复添加这个计算出的增量来计算。数据缓冲区必须表现良好。

代码语言:javascript
复制
void fillwithscalar(void *buffer, length, void *value, void *arr)

一个指向使用单个标量value的地址填充给定长度的连续buffer的函数的指针。最后一个参数是所需用于变长数组的 itemsize 的数组。

代码语言:javascript
复制
int sort(void *start, length, void *arr)

一个指向特定排序算法的函数指针数组。可以使用一个关键字(到目前为止定义了NPY_QUICKSORTNPY_HEAPSORTNPY_MERGESORT)。这些排序是在假定连续和对齐的数据上进行的。

代码语言:javascript
复制
int argsort(void *start, *result, length, void *arr)

一个指向此数据类型的排序算法的函数指针数组。可用于排序的排序算法与 sort 相同。产生排序的索引被返回到result中(必须初始化为包含 0 到length-1的索引)。

代码语言:javascript
复制
*castdict

可以是NULL或包含用户定义数据类型的低级转换函数的字典。每个函数都包装在一个PyCapsule*中,并以数据类型编号为键。

代码语言:javascript
复制
scalarkind( *arr)

用于确定此类型的标量应如何解释的函数。参数是一个包含数据的 0 维数组(如果需要确定标量的种类,则需要该数据)。返回值必须是类型为NPY_SCALARKIND的值。

代码语言:javascript
复制
int **cancastscalarkindto

可以是NULL或一个包含NPY_NSCALARKINDS指针的数组。这些指针每个都应该是NULL,或者是指向整数数组的指针(以NPY_NOTYPE终止),指示此数据类型的指定种类的标量可以安全地转换为的数据类型(通常意味着不会失去精度)。

代码语言:javascript
复制
int *cancastto

可以是NULL或一个整数数组(以NPY_NOTYPE终止),指示此数据类型可以安全地转换为的数据类型(通常意味着不会失去精度)。

代码语言:javascript
复制
void fastclip(void *in, n_in, void *min, void *max, void *out)

自版本 1.17 起弃用:使用此函数将在np.clip时产生弃用警告。不再使用此函数,数据类型必须使用PyUFunc_RegisterLoopForDescr将自定义循环附加到np.core.umath.clipnp.minimumnp.maximum

自版本 1.19 起弃用:设置此函数已被弃用,应始终为NULL,如果设置,将被忽略。

in中读取n_in项,并在其指向的限制范围内写入到out,如果超出范围,则写入相应的限制值。内存段必须是连续的且行为良好,minmax中的一个可以是NULL,但不能同时为空。

代码语言:javascript
复制
void fastputmask(void *in, void *mask, n_in, void *values, nv)

自版本 1.19 起弃用:设置此函数已被弃用,应始终为NULL,如果设置,将被忽略。

一个函数,它接受一个指向长度为n_in项的数组的指针in,一个指向长度为n_in的布尔值数组的指针mask,以及一个指向长度为nv项的数组的指针vals。将vals中的项复制到in中,其中mask中的值为非零,如果nv < n_in,则根据需要平铺vals。所有数组必须是连续的且行为良好。

代码语言:javascript
复制
void fasttake(void *dest, void *src, *indarray, nindarray, n_outer, m_middle, nelem, clipmode)

自版本 1.19 起弃用:设置此函数已被弃用,应始终为NULL,如果设置,将被忽略。

一个函数,它接受一个指针src,指向一个 C 连续的、行为良好的段,解释为形状为(n_outer, nindarray, nelem)的三维数组,一个指向m_middle整数索引的 C 连续的、行为良好的段的指针indarray,以及一个指向 C 连续的、行为良好的段的指针dest,解释为形状为(n_outer, m_middle, nelem)的三维数组。indarray 中的索引用于沿第二维索引src,并将对应的nelem项的块复制到dest中。clipmode(可以取值NPY_RAISENPY_WRAPNPY_CLIP)确定如何处理小于 0 或大于nindarray的索引。

代码语言:javascript
复制
int argmin(void *data, n, *min_ind, void *arr)

一个函数指针,用于检索从data指向的元素开始的包含n个元素的arr中最小元素的索引。此函数要求内存段是连续的且行为良好。返回值始终为 0。最小元素的索引将返回到min_ind中。

PyArray_Type 类型对象实现了许多Python 对象的特性,包括tp_as_numbertp_as_sequencetp_as_mappingtp_as_buffer 接口。富比较 也与新式属性查找一起使用,用于成员(tp_members)和属性(tp_getset)的访问。PyArray_Type 也可以被子类型化。

提示

tp_as_number 方法使用一种通用方法调用已注册用于处理操作的任何函数。当导入_multiarray_umath 模块时,它将所有数组的数值操作设置为相应的 ufuncs。可以使用PyUFunc_ReplaceLoopBySignature 来更改此选择。tp_strtp_repr 方法也可以使用PyArray_SetStringFunction 进行更改。

PyUFunc_Type 和 PyUFuncObject
代码语言:javascript
复制
PyUFunc_Type

ufunc 对象是通过创建PyUFunc_Type来实现的。 它是一种非常简单的类型,只实现了基本的 getAttribute 行为、打印行为,并且有 call 行为,这样这些对象就可以像函数一样。 ufunc 的基本思想是保存对支持操作的数据类型的快速 1 维(向量)循环的引用。 所有这些一维循环都具有相同的签名,并且是创建新 ufunc 的关键。 它们由通用循环代码适当调用以实现 N 维函数。 还为浮点和复数浮点数组定义了一些通用的一维循环,允许你使用单个标量函数(例如atanh)来定义 ufunc。

代码语言:javascript
复制
type PyUFuncObject

ufunc 的核心是PyUFuncObject,其中包含调用执行实际工作的基础 C 代码循环所需的所有信息。 虽然这里描述了这一点以确保兼容性: infotext default可以在不同的 NumPy 版本中更改。 为了确保兼容性。

  • 绝不声明结构的非指针实例
  • 永远不要执行指针算术
  • 永远不要使用sizeof(PyUFuncObject)

它具有以下结构:

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  nin;
  int  nout;
  int  nargs;
  int  identity;
  PyUFuncGenericFunction  *functions;
  void  **data;
  int  ntypes;
  int  reserved1;
  const  char  *name;
  char  *types;
  const  char  *doc;
  void  *ptr;
  PyObject  *obj;
  PyObject  *userloops;
  int  core_enabled;
  int  core_num_dim_ix;
  int  *core_num_dims;
  int  *core_dim_ixs;
  int  *core_offsets;
  char  *core_signature;
  PyUFunc_TypeResolutionFunc  *type_resolver;
  PyUFunc_LegacyInnerLoopSelectionFunc  *legacy_inner_loop_selector;
  void  *reserved2;
  npy_uint32  *op_flags;
  npy_uint32  *iter_flags;
  /* new in API version 0x0000000D */
  npy_intp  *core_dim_sizes;
  npy_uint32  *core_dim_flags;
  PyObject  *identity_value;
  /* Further private slots (size depends on the NumPy version) */
}  PyUFuncObject; 
代码语言:javascript
复制
int nin

输入参数的数量。

代码语言:javascript
复制
int nout

输出参数的数量。

代码语言:javascript
复制
int nargs

参数的总数(* nin * + * nout *)。 这必须小于NPY_MAXARGS

代码语言:javascript
复制
int identity

PyUFunc_OnePyUFunc_ZeroPyUFunc_MinusOnePyUFunc_NonePyUFunc_ReorderableNonePyUFunc_IdentityValue中的任何一个,以指示此操作的标识。 仅用于对空数组进行类似缩小的调用。

代码语言:javascript
复制
void functions(char **args, *dims, *steps, void *extradata)

一个函数指针数组 - 每种 ufunc 支持的数据类型一个。 这是被调用以实现基础功能dims[0]次的向量循环。 第一个参数args是一个* nargs 指针的数组,指向行为良好的内存。 首先是输入参数数据的指针,然后是输出参数数据的指针。 必须跳过多少字节才能到达序列中下一个元素由 steps 数组中的对应条目指定。 最后一个参数允许循环接收额外信息。 通常用于使单个通用向量循环用于多个函数。 在这种情况下,要调用的实际标量函数被传递为 extradata *。 这个函数指针数组的大小是 ntypes。

代码语言:javascript
复制
void **data

要传递给 1-d 向量循环的额外数据,如果不需要额外数据则为NULL。这个 C 数组必须与函数数组的大小相同( ntypes)。如果不需要额外数据,则使用NULL。几个用于 UFuncs 的 C API 调用只是利用这些额外数据运行 1-d 向量循环,以接收指向要调用的实际函数的指针。

代码语言:javascript
复制
int ntypes

ufunc 支持的数据类型数。这个数字指定可用的不同 1-d 循环(内置数据类型)的数量。

代码语言:javascript
复制
int reserved1

未使用。

代码语言:javascript
复制
char *name

为 ufunc 的字符串名称。这是动态使用的,用于构建 ufunc 的 doc 属性。

代码语言:javascript
复制
char *types

一个 (nargs \times ntypes) 8 位类型编号数组,包含每个支持(内置)数据类型的函数的类型签名。对于每个 ntypes 函数,该数组中对应的一组类型编号显示了如何在 1-d 向量循环中解释 args 参数。这些类型编号不必是相同类型,支持混合类型的 ufunc。

代码语言:javascript
复制
char *doc

用于 ufunc 的文档。不应包含函数签名,因为在检索 doc 时动态生成。

代码语言:javascript
复制
void *ptr

任何动态分配的内存。目前,这用于从 Python 函数创建动态 ufunc,用于存储类型、数据和名称成员的空间。

代码语言:javascript
复制
*obj

对于从 Python 函数动态创建的 ufunc,该成员持有对底层 Python 函数的引用。

代码语言:javascript
复制
*userloops

用户定义的 1-d 向量循环的字典(存储为 CObject 指针)用于用户定义的类型。用户可以为任何用户定义的类型注册循环。它通过类型编号检索。用户定义的类型编号总是大于NPY_USERDEF

代码语言:javascript
复制
int core_enabled

标量 ufunc 为 0;广义 ufunc 为 1

代码语言:javascript
复制
int core_num_dim_ix

签名中具有不同核心维度名称的数量

代码语言:javascript
复制
int *core_num_dims

每个参数的核心维度数

代码语言:javascript
复制
int *core_dim_ixs

展平形式的维度索引;参数k的索引存储在core_dim_ixs[core_offsets[k] : core_offsets[k] + core_numdims[k]]

代码语言:javascript
复制
int *core_offsets

每个参数在core_dim_ixs中第 1 个核心维度的位置,相当于 cumsum(core_num_dims)

代码语言:javascript
复制
char *core_signature

核心签名字符串

代码语言:javascript
复制
PyUFunc_TypeResolutionFunc *type_resolver

解析类型并填充输入和输出的 dtypes 的函数

代码语言:javascript
复制
PyUFunc_LegacyInnerLoopSelectionFunc *legacy_inner_loop_selector

从版本 1.22 起弃用:此插槽存在一些回退支持,但最终将被移除。依赖于此的通用函数最终将需要移植。请参阅NEP 41NEP 43

代码语言:javascript
复制
void *reserved2

用于可能的具有不同签名的未来循环选择器。

代码语言:javascript
复制
op_flags

为每个 ufunc 操作数覆盖默认操作数标志。

代码语言:javascript
复制
iter_flags

为 ufunc 覆盖默认 nditer 标志。

添加在 API 版本 0x0000000D 中

代码语言:javascript
复制
*core_dim_sizes

对于每个不同的核心维度,如果 UFUNC_CORE_DIM_SIZE_INFERRED0,则可能的 frozen 大小

代码语言:javascript
复制
*core_dim_flags

对于每个不同的核心维度,一组标志(UFUNC_CORE_DIM_CAN_IGNOREUFUNC_CORE_DIM_SIZE_INFERRED

代码语言:javascript
复制
*identity_value

缩减的标识,当 PyUFuncObject.identity 等于 PyUFunc_IdentityValue 时。

代码语言:javascript
复制
UFUNC_CORE_DIM_CAN_IGNORE

如果维度名称以 ? 结尾

代码语言:javascript
复制
UFUNC_CORE_DIM_SIZE_INFERRED

如果维度大小将由操作数而不是从 frozen 签名确定

PyArrayIter_Type 和 PyArrayIterObject
代码语言:javascript
复制
PyArrayIter_Type

这是一个迭代器对象,使得可以轻松地循环遍历 N 维数组。它是从 ndarray 的 flat 属性返回的对象。它还在整个实现内部广泛使用,以循环遍历 N 维数组。实现了 tp_as_mapping 接口,以便可以索引迭代器对象(使用 1-d 索引),并且通过 tp_methods 表实现了一些方法。此对象实现了 next 方法,并且可以在 Python 中使用任何迭代器可以使用的地方。

代码语言:javascript
复制
type PyArrayIterObject

PyArrayIter_Type 对象对应的 C 结构是 PyArrayIterObjectPyArrayIterObject 用于跟踪指向 N 维数组的指针。它包含用于快速遍历数组的相关信息。指针可以通过三种基本方式进行调整:1)以 C 风格连续地前进到数组中的“下一个”位置,2)前进到数组中的任意 N 维坐标,和 3)前进到数组中的任意一维索引。PyArrayIterObject 结构的成员在这些计算中使用。迭代器对象保存关于数组的自己的维度和跨度信息。这可以根据需要进行“广播”,或者仅循环特定维度。

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  nd_m1;
  npy_intp  index;
  npy_intp  size;
  npy_intp  coordinates[NPY_MAXDIMS];
  npy_intp  dims_m1[NPY_MAXDIMS];
  npy_intp  strides[NPY_MAXDIMS];
  npy_intp  backstrides[NPY_MAXDIMS];
  npy_intp  factors[NPY_MAXDIMS];
  PyArrayObject  *ao;
  char  *dataptr;
  npy_bool  contiguous;
}  PyArrayIterObject; 
代码语言:javascript
复制
int nd_m1

(N-1) 其中 (N) 是底层数组中的维数。

代码语言:javascript
复制
index

数组中的当前 1-d 索引。

代码语言:javascript
复制
size

底层数组的总大小。

代码语言:javascript
复制
*coordinates

对数组的 (N) 维索引。

代码语言:javascript
复制
*dims_m1

数组在每个维度上的大小减去 1。

代码语言:javascript
复制
*strides

数组的跨度。在每个维度跳转到下一个元素所需的字节数。

代码语言:javascript
复制
*backstrides

从维度的末尾跳回到其开头所需的字节数。请注意 backstrides[k] == strides[k] * dims_m1[k],但这里存储为一种优化。

代码语言:javascript
复制
*factors

此数组用于从 1-d 索引计算 N-d 索引。它包含维度的所需乘积。

代码语言:javascript
复制
*ao

指向创建此迭代器代表的底层 ndarray 的指针。

代码语言:javascript
复制
char *dataptr

此成员指向由索引指示的 ndarray 中的元素。

代码语言:javascript
复制
contiguous

若底层数组是 NPY_ARRAY_C_CONTIGUOUS,则此标志为真。在可能的情况下,可用于简化计算。

如何在 C 级别上使用数组迭代器在后续章节中有更详细的解释。通常,您无需关心迭代器对象的内部结构,只需通过宏 PyArray_ITER_NEXT (it)、PyArray_ITER_GOTO (it, dest) 或 PyArray_ITER_GOTO1D (it, index) 与其进行交互。所有这些宏都需要参数 it 为 PyArrayIterObject*。

PyArrayMultiIter_Type 和 PyArrayMultiIterObject
代码语言:javascript
复制
PyArrayMultiIter_Type

该类型提供了一种封装广播概念的迭代器。它允许 (N) 个数组一起进行广播,使循环以 C 样式连续方式在广播的数组上进行。相应的 C 结构是 PyArrayMultiIterObject,其内存布局必须以传递给 PyArray_Broadcast (obj) 函数的任何对象 obj 开始。通过调整数组迭代器来执行广播,使得每个迭代器表示广播的形状和大小,但其步长被调整,以便在每次迭代中使用数组的正确元素。

代码语言:javascript
复制
type PyArrayMultiIterObject
代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  numiter;
  npy_intp  size;
  npy_intp  index;
  int  nd;
  npy_intp  dimensions[NPY_MAXDIMS];
  PyArrayIterObject  *iters[NPY_MAXDIMS];
}  PyArrayMultiIterObject; 
代码语言:javascript
复制
int numiter

需要广播到相同形状的数组的数量。

代码语言:javascript
复制
size

总的广播大小。

代码语言:javascript
复制
index

当前(1-d)索引进入广播结果。

代码语言:javascript
复制
int nd

广播结果中的维数。

代码语言:javascript
复制
*dimensions

广播结果的形状(仅使用 nd 槽)。

代码语言:javascript
复制
**iters

一个迭代器对象数组,其中包含要一起广播的数组的迭代器。返回时,迭代器会进行调整以进行广播。

PyArrayNeighborhoodIter_Type 和 PyArrayNeighborhoodIterObject
代码语言:javascript
复制
PyArrayNeighborhoodIter_Type

这是一个迭代器对象,可轻松循环遍历 N 维邻域。

代码语言:javascript
复制
type PyArrayNeighborhoodIterObject

PyArrayNeighborhoodIter_Type 对象对应的 C 结构是 PyArrayNeighborhoodIterObject

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  nd_m1;
  npy_intp  index,  size;
  npy_intp  coordinates[NPY_MAXDIMS]
  npy_intp  dims_m1[NPY_MAXDIMS];
  npy_intp  strides[NPY_MAXDIMS];
  npy_intp  backstrides[NPY_MAXDIMS];
  npy_intp  factors[NPY_MAXDIMS];
  PyArrayObject  *ao;
  char  *dataptr;
  npy_bool  contiguous;
  npy_intp  bounds[NPY_MAXDIMS][2];
  npy_intp  limits[NPY_MAXDIMS][2];
  npy_intp  limits_sizes[NPY_MAXDIMS];
  npy_iter_get_dataptr_t  translate;
  npy_intp  nd;
  npy_intp  dimensions[NPY_MAXDIMS];
  PyArrayIterObject*  _internal_iter;
  char*  constant;
  int  mode;
}  PyArrayNeighborhoodIterObject; 
PyArrayFlags_Type 和 PyArrayFlagsObject
代码语言:javascript
复制
PyArrayFlags_Type

当从 Python 中检索 flags 属性时,将构建此特殊内置对象的特殊类型。这种特殊类型通过将它们作为属性访问或通过将对象视为具有标志名称条目的字典来访问它们,使得更容易处理不同的标志。

代码语言:javascript
复制
type PyArrayFlagsObject
代码语言:javascript
复制
typedef  struct  PyArrayFlagsObject  {
  PyObject_HEAD
  PyObject  *arr;
  int  flags;
}  PyArrayFlagsObject; 
ScalarArrayTypes

每种内置数据类型在 Python 中都有一个类型。这些大多是简单的包装器,用于对应 C 中的相应数据类型。这些类型的 C 名称为Py{TYPE}ArrType_Type,其中{TYPE}可以是

BoolByteShortIntLongLongLongUByteUShortUIntULongULongLongHalfFloatDoubleLongDoubleCFloatCDoubleCLongDoubleStringUnicodeVoidObject

这些类型名称是 C-API 的一部分,因此可以在扩展的 C 代码中创建。还有一个PyIntpArrType_Type和一个PyUIntpArrType_Type,它们是平台上可以容纳指针的整数类型之一的简单替代品。这些标量对象的结构对 C 代码不可见。函数PyArray_ScalarAsCtype(…)可以用于从数组标量中提取 C 类型值,函数PyArray_Scalar(…)可以用于从 C 值构造数组标量。

其他 C-结构

开发 NumPy 时发现有几个新的 C-结构很有用。这些 C 结构至少在一个 C-API 调用中使用,因此在这里记录。定义这些结构的主要原因是为了方便使用 Python ParseTuple C-API,将 Python 对象转换为有用的 C 对象。

PyArray_Dims
代码语言:javascript
复制
type PyArray_Dims

当形状和/或步幅信息被解释时,这个结构非常有用。结构如下:

代码语言:javascript
复制
typedef  struct  {
  npy_intp  *ptr;
  int  len;
}  PyArray_Dims; 

这个结构体的成员是

代码语言:javascript
复制
*ptr

一个指向(npy_intp)整数列表的指针,通常表示数组形状或数组步幅。

代码语言:javascript
复制
int len

整数列表的长度。假定安全访问ptr[0]至ptr[len-1]。

PyArray_Chunk
代码语言:javascript
复制
type PyArray_Chunk

这与 Python 中的缓冲对象结构相当,直到 ptr 成员。在 32 位平台上(如果NPY_SIZEOF_INT == NPY_SIZEOF_INTP),len 成员也与缓冲对象的等效成员匹配。它用于表示通用的单段内存块。

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  PyObject  *base;
  void  *ptr;
  npy_intp  len;
  int  flags;
}  PyArray_Chunk; 

成员是

代码语言:javascript
复制
*base

此内存块来自的 Python 对象。需要这样才能正确地计算内存。

代码语言:javascript
复制
void *ptr

单段内存块开始的指针。

代码语言:javascript
复制
len

段的长度(以字节为单位)。

代码语言:javascript
复制
int flags

用来解释内存的任何数据标志(例如 NPY_ARRAY_WRITEABLE)。

PyArrayInterface

另请参阅

数组接口协议

代码语言:javascript
复制
type PyArrayInterface

PyArrayInterface 结构被定义为 NumPy 和其他扩展模块可以使用快速的数组接口协议。支持快速数组接口协议的对象的__array_struct__方法应该返回一个包含指向PyArrayInterface结构的相关细节的指针的PyCapsule。创建新数组后,应该对属性执行DECREF,这将释放PyArrayInterface结构。记得对检索到的__array_struct__属性的对象进行INCREF,并将新的PyArrayObject的 base 成员指向这个相同的对象。以这种方式管理数组的内存将是正确的。

代码语言:javascript
复制
typedef  struct  {
  int  two;
  int  nd;
  char  typekind;
  int  itemsize;
  int  flags;
  npy_intp  *shape;
  npy_intp  *strides;
  void  *data;
  PyObject  *descr;
}  PyArrayInterface; 
代码语言:javascript
复制
int two

整数 2 作为一个健全性检查。

代码语言:javascript
复制
int nd

数组中的维数。

代码语言:javascript
复制
char typekind

根据类型字符串约定,指示存在何种类型数组的字符,‘t’ -> 位域,‘b’ -> 布尔值,‘i’ -> 有符号整数,‘u’ -> 无符号整数,‘f’ -> 浮点数,‘c’ -> 复数浮点数,‘O’ -> 对象,‘S’ -> (字节)字符串,‘U’ -> Unicode,‘V’ -> 空。

代码语言:javascript
复制
int itemsize

数组中每个项需要的字节数。

代码语言:javascript
复制
int flags

NPY_ARRAY_C_CONTIGUOUS (1), NPY_ARRAY_F_CONTIGUOUS (2), NPY_ARRAY_ALIGNED (0x100), NPY_ARRAY_NOTSWAPPED (0x200),或NPY_ARRAY_WRITEABLE (0x400),指示有关数据的一些信息。NPY_ARRAY_ALIGNEDNPY_ARRAY_C_CONTIGUOUSNPY_ARRAY_F_CONTIGUOUS标志实际上可以从其他参数中确定。标志NPY_ARR_HAS_DESCR (0x800)也可以设置为指示给消耗版本 3 数组接口的对象,这个结构的 descr 成员是存在的(对消耗版本 2 数组接口的对象会被忽略)。

代码语言:javascript
复制
*shape

包含每个维度中数组大小的数组。

代码语言:javascript
复制
*strides

包含每个维度中移动到下一个元素所需的字节数的数组。

代码语言:javascript
复制
void *data

数组的第一个元素的指针。

代码语言:javascript
复制
*descr

更详细描述数据类型的 Python 对象(与__array_interface__中的descr键相同)。如果typekinditemsize提供足够信息,则这可以是NULL。除非flags中打开了 NPY_ARR_HAS_DESCR 标志,否则也会忽略此字段。

内部使用的结构

内部,代码使用一些额外的 Python 对象主要用于内存管理。这些类型无法直接从 Python 访问,也不暴露给 C-API。它们在这里仅用于完整性和帮助理解代码。

代码语言:javascript
复制
type PyUFunc_Loop1d

一个包含为每个用户定义的数据类型的每个已定义签名定义 1-d 循环的信息的 C-结构的简单链接列表。

代码语言:javascript
复制
PyArrayMapIter_Type

高级索引由这种 Python 类型处理。它只是包装了包含高级数组索引所需变量的 C 结构的松散包装。

代码语言:javascript
复制
type PyArrayMapIterObject

PyArrayMapIter_Type相关联的 C 结构。如果您试图理解高级索引映射代码,这个结构很有用。它在arrayobject.h头文件中定义。这种类型不暴露给 Python,可以用 C 结构替换。作为 Python 类型,它利用了引用计数内存管理。

定义的新 Python 类型

Python 类型相当于 Python 中的类。通过构建一个新的 Python 类型,您可以为 Python 提供一个新对象。ndarray对象就是在 C 中定义的一个新类型的示例。定义新类型的基本步骤是:

  1. 创建一个与PyObject结构本身二进制兼容但包含特定对象所需的附加信息的 C 结构(通常命名为Py{Name}Object);
  2. 填充PyTypeObject表(由PyObject结构的 ob_type 成员指向的):指向实现该类型所需行为的函数的指针。

而不是为 Python 类定义行为的特殊方法名称,有指向实现所需结果的功能表。自 Python 2.2 以来,PyTypeObject本身已经变得动态,允许在 C 中“从其他 C 类型”继承的 C 类型,“在 Python 中子类化”。子类型从其父类型继承属性和方法。

有两个主要的新类型:ndarrayPyArray_Type )和ufuncPyUFunc_Type )。其他类型起辅助作用:PyArrayIter_TypePyArrayMultiIter_TypePyArrayDescr_TypePyArrayIter_Typendarray的平坦迭代器类型(在获取 flat 属性时返回的对象)。PyArrayMultiIter_Type是调用broadcast()时返回的对象类型。它处理迭代和广播集合的嵌套序列。另外,PyArrayDescr_Type是数据类型描述符类型,其实例描述数据。最后,还有 21 种新的标量数组类型,这些是对应于数组的可用基本数据类型的新 Python 标量。另外还有 10 种其他类型,这些是占位符,允许数组标量适应实际 Python 类型的层次结构。

PyArray_TypePyArrayObject
代码语言:javascript
复制
PyArray_Type

ndarray的 Python 类型是PyArray_Type。在 C 中,每个ndarray都是指向PyArrayObject结构体的指针。该结构体的ob_type成员包含一个指向PyArray_Type类型对象的指针。

代码语言:javascript
复制
type PyArrayObject
代码语言:javascript
复制
type NPY_AO

PyArrayObject C 结构体包含数组的所有必需信息。所有ndarray实例(及其子类)都将具有此结构。为了将来的兼容性,应使用提供的宏来访问这些结构成员。如果需要更短的名称,可以使用NPY_AO(已弃用),其定义等同于PyArrayObject。已弃用直接访问结构字段。请改为使用PyArray_*(arr)形式。从 NumPy 1.20 开始,这个结构的大小不被视为 NumPy ABI 的一部分(请参见成员列表末尾的说明)。

代码语言:javascript
复制
typedef  struct  PyArrayObject  {
  PyObject_HEAD
  char  *data;
  int  nd;
  npy_intp  *dimensions;
  npy_intp  *strides;
  PyObject  *base;
  PyArray_Descr  *descr;
  int  flags;
  PyObject  *weakreflist;
  /* version dependent private members */
}  PyArrayObject; 
代码语言:javascript
复制
PyObject_HEAD

这对所有 Python 对象都是必需的。它由(至少)一个引用计数成员(ob_refcnt)和一个指向类型对象(ob_type)的指针组成。(如果 Python 是使用特殊选项编译的,可能还有其他元素,请参见 Python 源代码树中的 Include/object.h 了解更多信息)。ob_type 成员指向 Python 类型对象。

代码语言:javascript
复制
char *data

可通过PyArray_DATA访问,此数据成员是数组的第一个元素的指针。这个指针可以(通常应该)重塑为数组的数据类型。

代码语言:javascript
复制
int nd

一个整数,提供此数组的维度数量。当 nd 为 0 时,该数组有时被称为 0 阶数组。这样的数组具有未定义的维度和跨度,无法访问。宏 PyArray_NDIMndarraytypes.h 中定义,指向这个数据成员。NPY_MAXDIMS 是任何数组的最大维度数量。

代码语言:javascript
复制
*dimensions

一个整数数组,为每个维度提供每个维度的形状,只要 nd (\geq) 1。整数总是足够大以容纳平台上的指针,因此维度大小仅受内存限制。PyArray_DIMS 是与这个数据成员相关联的宏。

代码语言:javascript
复制
*strides

一个整数数组,为每个维度提供跳过的字节数,以便在该维度中到达下一个元素。与宏 PyArray_STRIDES 相关联。

代码语言:javascript
复制
*base

PyArray_BASE 指向,这个成员用于保存与该数组相关的另一个 Python 对象的指针。有两种用例:

  • 如果这个数组不拥有自己的内存,那么 base 指向拥有它的 Python 对象(也许是另一个数组对象)。
  • 如果这个数组设置了 NPY_ARRAY_WRITEBACKIFCOPY 标志,那么这个数组是一个“行为异常”的数组的工作副本。

当调用 PyArray_ResolveWritebackIfCopy 时,将使用该数组的内容更新由 base 指向的数组。

代码语言:javascript
复制
*descr

一个指向数据类型描述对象的指针(参见下文)。数据类型描述对象是一个新的内置类型的实例,它允许对内存进行通用描述。每种支持的数据类型都有一个描述结构体。这个描述结构体包含有关该类型的有用信息,以及指向实现特定功能的函数指针表的指针。顾名思义,它与宏 PyArray_DESCR 相关联。

代码语言:javascript
复制
int flags

由宏 PyArray_FLAGS 指向,这个数据成员表示数据指向的内存应该如何解释的标志。可能的标志有 NPY_ARRAY_C_CONTIGUOUSNPY_ARRAY_F_CONTIGUOUSNPY_ARRAY_OWNDATANPY_ARRAY_ALIGNEDNPY_ARRAY_WRITEABLENPY_ARRAY_WRITEBACKIFCOPY

代码语言:javascript
复制
*weakreflist

这个成员允许数组对象具有弱引用(使用 weakref 模块)。

注意

进一步的成员被视为私有和版本相关。如果结构的大小对您的代码很重要,必须特别小心。当这是相关的可能使用案例是在 C 中进行子类化。如果您的代码依赖于sizeof(PyArrayObject)是恒定的,您必须在导入时添加以下检查:

代码语言:javascript
复制
if  (sizeof(PyArrayObject)  <  PyArray_Type.tp_basicsize)  {
  PyErr_SetString(PyExc_ImportError,
  "Binary incompatibility with NumPy, must recompile/update X.");
  return  NULL;
} 

要确保您的代码不必针对特定的 NumPy 版本进行编译,可以添加一个常量,为 NumPy 中的变化留出空间。 确保兼容任何未来的 NumPy 版本的解决方案需要运行时计算偏移量和分配大小。

PyArrayDescr_Type 和 PyArray_Descr
代码语言:javascript
复制
PyArrayDescr_Type

PyArrayDescr_Type 是用于描述组成数组的字节该如何解释的数据类型描述符对象的内置类型。有 21 个静态定义的PyArray_Descr对象用于内置数据类型。尽管这些参与引用计数,但它们的引用计数永远不应该为零。还维护了一个动态的用户定义的PyArray_Descr对象表。一旦“注册”了数据类型描述符对象,就不应该将其释放。函数PyArray_DescrFromType (…)可以用于从枚举类型号(内置或用户定义的)中检索PyArray_Descr对象。

代码语言:javascript
复制
type PyArray_Descr

PyArray_Descr 结构位于PyArrayDescr_Type的核心。虽然此处为完整起见进行了描述,但应将其视为 NumPy 的内部结构,并通过PyArrayDescr_*PyDataType*函数和宏来操作。此结构的大小可能会随 NumPy 的不同版本而发生变化。为确保兼容性:

  • 永远不要声明结构的非指针实例
  • 永远不要执行指针算术运算
  • 永远不要使用sizeof(PyArray_Descr)

它有以下结构:

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  PyTypeObject  *typeobj;
  char  kind;
  char  type;
  char  byteorder;
  char  flags;
  int  type_num;
  int  elsize;
  int  alignment;
  PyArray_ArrayDescr  *subarray;
  PyObject  *fields;
  PyObject  *names;
  PyArray_ArrFuncs  *f;
  PyObject  *metadata;
  NpyAuxData  *c_metadata;
  npy_hash_t  hash;
}  PyArray_Descr; 
代码语言:javascript
复制
*typeobj

指向对应于此数组元素的 Python 类型的类型对象的指针。 对于内置类型,这指向对应的数组标量。 对于用户定义的类型,这应指向用户定义的类型对象。 这个类型对象可以继承自数组标量,也可以不继承。 如果它不继承自数组标量,那么flags成员中应该设置NPY_USE_GETITEMNPY_USE_SETITEM标志。

代码语言:javascript
复制
char kind

表示数组种类的字符代码(使用数组接口类型字符串表示法)。 'b’代表布尔值,'i’代表有符号整数,'u’代表无符号整数,'f’代表浮点数,'c’代表复数浮点数,'S’代表 8 位零终止字节,'U’代表 32 位/字符的 unicode 字符串,'V’代表任意长度。

代码语言:javascript
复制
char type

传统的字符代码,表示数据类型。

代码语言:javascript
复制
char byteorder

一个表示字节顺序的字符:‘>’(大端),‘<’(小端),‘=’(本机),‘|’(无关,忽略)。所有内置数据类型都具有字节顺序‘=’。

代码语言:javascript
复制
char flags

一个确定数据类型是否展示类似对象数组的行为的数据类型位标志。这个成员中的每个位是一个标志,它们被命名为:

  • NPY_ITEM_REFCOUNT
  • NPY_ITEM_HASOBJECT
  • NPY_LIST_PICKLE
  • NPY_ITEM_IS_POINTER
  • NPY_NEEDS_INIT
  • NPY_NEEDS_PYAPI
  • NPY_USE_GETITEM
  • NPY_USE_SETITEM
  • NPY_FROM_FIELDS
  • NPY_OBJECT_DTYPE_FLAGS
代码语言:javascript
复制
int type_num

一个唯一标识数据类型的数字。对于新数据类型,当数据类型被注册时,分配这个数字。

代码语言:javascript
复制
int elsize

对于始终相同大小的数据类型(例如 long),这个成员保存数据类型的大小。对于灵活的数据类型,不同的数组可能具有不同的元素大小,这个值应该为 0。

代码语言:javascript
复制
int alignment

提供这个数据类型的对齐信息的数字。具体来说,它显示编译器在一个 2 元结构的开始处(其第一个元素是一个char)放置该类型的项的距离:offsetof(struct {char c; type v;}, v)

代码语言:javascript
复制
*subarray

如果这是非NULL,那么这个数据类型描述符是另一个数据类型描述符的 C 风格连续数组。换句话说,这个描述符描述的每个元素实际上是另一个基本描述符的数组。这对于作为另一个数据类型描述符中字段的数据类型描述符最有用。如果这个非NULL,则 fields 成员应该为NULL(但是 base 描述符的 fields 成员可以为非NULL)。

代码语言:javascript
复制
type PyArray_ArrayDescr
代码语言:javascript
复制
typedef  struct  {
  PyArray_Descr  *base;
  PyObject  *shape;
}  PyArray_ArrayDescr; 
代码语言:javascript
复制
*base

基本类型的数据类型描述符对象。

代码语言:javascript
复制
*shape

子数组的形状(始终是 C 风格连续)作为 Python 元组。

代码语言:javascript
复制
*fields

如果这不是 NULL,则这个数据类型描述符具有由 Python 字典描述的字段,其键是名称(如果给定也是标题),其值是描述字段的元组。请记住,数据类型描述符总是描述一组固定长度的字节。字段是该总体固定长度集合的命名子区域。字段由另一个数据类型描述符和一个字节偏移的元组描述。可选地,元组可以包含通常是 Python 字符串的标题。这些元组被放在此字典中,以名称(如果给定也是标题)为键。

代码语言:javascript
复制
*names

字段名称的有序元组。如果未定义字段,则为 NULL。

代码语言:javascript
复制
*f

指向包含类型需要实现内部功能的函数的结构的指针。这些函数与后面描述的通用函数(ufuncs)不同。它们的签名可以任意变化。

代码语言:javascript
复制
*metadata

关于这个数据类型的元数据。

代码语言:javascript
复制
*c_metadata

特定于特定 dtype 的 C 实现的元数据。添加到 NumPy 1.7.0 中。

代码语言:javascript
复制
type npy_hash_t
代码语言:javascript
复制
*hash

当前未使用。保留用于将来缓存哈希值。

代码语言:javascript
复制
NPY_ITEM_REFCOUNT

表示这种数据类型的项必须进行引用计数(使用Py_INCREFPy_DECREF)。

代码语言:javascript
复制
NPY_ITEM_HASOBJECT

NPY_ITEM_REFCOUNT相同。

代码语言:javascript
复制
NPY_LIST_PICKLE

表示必须在将数组转储为列表之前将这种数据类型的数组转换为列表。

代码语言:javascript
复制
NPY_ITEM_IS_POINTER

表示该项是指向其他数据类型的指针

代码语言:javascript
复制
NPY_NEEDS_INIT

表示必须初始化此数据类型的内存(设置为 0)。

代码语言:javascript
复制
NPY_NEEDS_PYAPI

表明此数据类型在访问时需要 Python C-API(因此,在需要数组访问时不要放弃 GIL)。

代码语言:javascript
复制
NPY_USE_GETITEM

在数组访问时,使用f->getitem函数指针而不是标准的转换为数组标量。如果不定义与数据类型一起使用的数组标量,必须使用。

代码语言:javascript
复制
NPY_USE_SETITEM

从数组标量创建一个 0-d 数组时,请使用f->setitem而不是标准的从数组标量复制。如果不定义与数据类型一起使用的数组标量,必须使用。

代码语言:javascript
复制
NPY_FROM_FIELDS

如果数据类型的任何字段中设置了这些位,则从父数据类型继承的位。目前(NPY_NEEDS_INIT | NPY_LIST_PICKLE | NPY_ITEM_REFCOUNT | NPY_NEEDS_PYAPI)。

代码语言:javascript
复制
NPY_OBJECT_DTYPE_FLAGS

对象数据类型的设置位:(NPY_LIST_PICKLE | NPY_USE_GETITEM | NPY_ITEM_IS_POINTER | NPY_ITEM_REFCOUNT | NPY_NEEDS_INIT | NPY_NEEDS_PYAPI)。

代码语言:javascript
复制
int PyDataType_FLAGCHK( *dtype, int flags)

如果对于数据类型对象设置了所有给定的标志,则返回 true。

代码语言:javascript
复制
int PyDataType_REFCHK( *dtype)

等效于PyDataType_FLAGCHKdtypeNPY_ITEM_REFCOUNT)。

代码语言:javascript
复制
type PyArray_ArrFuncs

实现内部功能的函数。并非所有这些函数指针必须对给定类型进行定义。所需成员是nonzerocopyswapcopyswapnsetitemgetitemcast。假定这些都是非NULL的,而NULL条目将导致程序崩溃。其他函数可能是NULL,这意味着该数据类型的功能将减少。 (同时,如果在注册用户定义的数据类型时NULL,则nonzero函数将填充为默认函数)。

代码语言:javascript
复制
typedef  struct  {
  PyArray_VectorUnaryFunc  *cast[NPY_NTYPES];
  PyArray_GetItemFunc  *getitem;
  PyArray_SetItemFunc  *setitem;
  PyArray_CopySwapNFunc  *copyswapn;
  PyArray_CopySwapFunc  *copyswap;
  PyArray_CompareFunc  *compare;
  PyArray_ArgFunc  *argmax;
  PyArray_DotFunc  *dotfunc;
  PyArray_ScanFunc  *scanfunc;
  PyArray_FromStrFunc  *fromstr;
  PyArray_NonzeroFunc  *nonzero;
  PyArray_FillFunc  *fill;
  PyArray_FillWithScalarFunc  *fillwithscalar;
  PyArray_SortFunc  *sort[NPY_NSORTS];
  PyArray_ArgSortFunc  *argsort[NPY_NSORTS];
  PyObject  *castdict;
  PyArray_ScalarKindFunc  *scalarkind;
  int  **cancastscalarkindto;
  int  *cancastto;
  PyArray_FastClipFunc  *fastclip;  /* deprecated */
  PyArray_FastPutmaskFunc  *fastputmask;  /* deprecated */
  PyArray_FastTakeFunc  *fasttake;  /* deprecated */
  PyArray_ArgFunc  *argmin;
}  PyArray_ArrFuncs; 

"表现正常"的概念用于描述函数指针。一个表现正常的段是指对齐且符合数据类型本机字节顺序的段。nonzerocopyswapcopyswapngetitemsetitem函数可以(而且必须)处理不正常的数组。其他函数要求内存段表现正常。

代码语言:javascript
复制
void cast(void *from, void *to, n, void *fromarr, void *toarr)

一串函数指针,用于将当前类型向所有其他内置类型转换。每个函数将一个由from指向的连续、对齐、未交换的缓冲区转换为一个由to指向的连续、对齐和未交换的缓冲区。要转换的项数由n给出,参数fromarrtoarr被解释为灵活数组的 PyArrayObjects 以获取 itemsize 信息。

代码语言:javascript
复制
*getitem(void *data, void *arr)

一个指向从由data指向的数组对象arr的单个元素返回标准 Python 对象的函数的指针。这个函数必须能够正确处理“不正常”(不对齐和/或交换)的数组。

代码语言:javascript
复制
int setitem( *item, void *data, void *arr)

一个指向将 Python 对象item设置到由data指向的数组arr中的函数的指针。这个函数处理“不正常的”数组。如果成功,返回值为零,否则返回一个负数(并设置一个 Python 错误)。

代码语言:javascript
复制
void copyswapn(void *dest, dstride, void *src, sstride, n, int swap, void *arr)
代码语言:javascript
复制
void copyswap(void *dest, void *src, int swap, void *arr)

这些成员都是指向从src复制数据到dest并在需要时进行swap的函数的指针。arr 的值仅用于灵活(NPY_STRINGNPY_UNICODENPY_VOID)数组(并且从arr->descr->elsize中获取)。第二个函数复制单个值,而第一个函数使用提供的步幅循环 n 次。这些函数可以处理不正常的src数据。如果src为 NULL,则不执行复制。如果swap为 0,则不进行字节交换。假定destsrc不重叠。如果它们重叠,则首先使用memmove(…),然后使用带有空值srccopyswap(n)

代码语言:javascript
复制
int compare(const void *d1, const void *d2, void *arr)

一个指向比较数组arr中由d1d2指向的两个元素的函数的指针。这个函数要求数组表现正常(对齐并且没有交换)。如果* d1 > * d2,返回值为 1;如果* d1 == * d2,返回值为 0;如果* d1 < * d2,返回值为-1。数组对象arr用于获取灵活数组的 itemsize 和字段信息。

代码语言:javascript
复制
int argmax(void *data, n, *max_ind, void *arr)

一个指向从由data指向的元素开始的arrn个元素中最大值的索引的函数的指针。这个函数要求内存段是连续的并且表现正常。返回值总是 0。最大元素的索引存储在max_ind中。

代码语言:javascript
复制
void dotfunc(void *ip1, is1, void *ip2, is2, void *op, n, void *arr)

指向一个函数的指针,用于将两个长度为n的序列相乘,并将它们相加,然后将结果放在arrop指向的元素中。两个序列的起始位置分别由ip1ip2指向。要达到每个序列的下一个元素,需要分别跳过is1is2 字节。此函数需要被认为是行为良好的(尽管不一定连续)内存。

代码语言:javascript
复制
int scanfunc(FILE *fd, void *ip, void *arr)

指向一个函数的指针,用于从文件描述符fd中以(scanf 风格)扫描相应类型的元素到ip指向的数组内存中。假定该数组是被认为是行为良好的。最后一个参数arr是要扫描到的数组。返回成功分配的接收参数的数量(如果在分配第一个接收参数之前发生匹配失败,这个数量可能为零),或者在分配第一个接收参数之前发生输入失败时返回 EOF。在报告错误时应该在不持有 Python GIL 的情况下调用此函数,并且会为错误报告而调用 GIL。

代码语言:javascript
复制
int fromstr(char *str, void *ip, char **endptr, void *arr)

指向一个函数的指针,用于将由str指向的字符串转换为相应类型的一个元素,并将其放入ip指向的内存位置。转换完成后,*endptr指向字符串的其余部分。最后一个参数arr是 ip 指向的数组(对于可变大小数据类型是必需的)。成功返回 0,失败返回-1。需要一个被认为是行为良好的数组。在报告错误时应该在不持有 Python GIL 的情况下调用此函数,并且会为错误报告而调用 GIL。

代码语言:javascript
复制
nonzero(void *data, void *arr)

指向一个函数的指针,如果data指向的arr项是非零则返回 TRUE。此函数可以处理行为不良的数组。

代码语言:javascript
复制
void fill(void *data, length, void *arr)

指向一个函数的指针,用于用数据填充给定长度的连续数组。数组的前两个元素必须已经填充了值。从这两个值中,将计算出一个增量,并且从第 3 个到最后一个元素将会反复地加上这个计算出的增量。数据缓冲区必须是行为良好的。

代码语言:javascript
复制
void fillwithscalar(void *buffer, length, void *value, void *arr)

指向一个函数的指针,用于使用给定的单一标量值向长度为给定length的连续buffer填充数据。最后一个参数是所需的用于变长数组获取 itemsize 的数组。

代码语言:javascript
复制
int sort(void *start, length, void *arr)

一个指向特定排序算法的函数指针数组。使用键(到目前为止已经定义了NPY_QUICKSORTNPY_HEAPSORT,和NPY_MERGESORT)可以获取特定的排序算法。这些排序是就地进行的,假定数据是连续的和对齐的。

代码语言:javascript
复制
int argsort(void *start, *result, length, void *arr)

一个指向用于此数据类型的排序算法的函数指针数组。与 sort 相同的排序算法可用。产生排序的索引将会返回在result中(必须初始化为包含 0 到length-1的索引)。

代码语言:javascript
复制
*castdict

要么为NULL,要么是包含用户定义数据类型的低级转换函数的字典。每个函数都被包装在一个PyCapsule*中,并由数据类型编号键入。

代码语言:javascript
复制
scalarkind( *arr)

用于确定应如何解释此类型标量的函数。参数为NULL或包含数据的 0 维数组(如果需要确定标量类型)。返回值必须是NPY_SCALARKIND类型。

代码语言:javascript
复制
int **cancastscalarkindto

要么为NULL,要么为NPY_SCALARKINDS指针数组。这些指针应该是NULL,或者指向整数数组(以NPY_NOTYPE结尾),表示此数据类型的标量可以安全转换为指定类型的数据类型(通常表示不会失去精度)。

代码语言:javascript
复制
int *cancastto

要么为NULL,要么为整数数组(以NPY_NOTYPE结尾),表示此数据类型可以安全转换为的数据类型(通常表示不会失去精度)。

代码语言:javascript
复制
void fastclip(void *in, n_in, void *min, void *max, void *out)

自版本 1.17 起弃用:使用此函数将在np.clip时产生弃用警告。该数据类型必须使用PyUFunc_RegisterLoopForDescr来将自定义循环附加到np.core.umath.clipnp.minimumnp.maximum

自版本 1.19 起弃用:设置此函数已被弃用,应始终为NULL,如果设置,将被忽略。

一个函数,从in中读取n_in个项目,并将读取的值写入out,如果在minmax指向的限制范围内,则在外部使用对应的限制。内存段必须是连续的且规范化的,并且minmax可能为NULL,但不能同时为NULL

代码语言:javascript
复制
void fastputmask(void *in, void *mask, n_in, void *values, nv)

自版本 1.19 起弃用:设置此函数已被弃用,应始终为NULL,如果设置,将被忽略。

一个函数,接受指向n_in个项目数组的指针in,指向n_in个布尔值的数组的指针mask,以及指向nv个项目的数组的指针vals。无需失去精度地将vals中的项复制到in中,只需在mask中的值非零时,根据需要平铺vals,如果nv < n_in。所有数组都必须是连续的且规范化的。

代码语言:javascript
复制
void fasttake(void *dest, void *src, *indarray, nindarray, n_outer, m_middle, nelem, clipmode)

自版本 1.19 起弃用:设置此函数已被弃用,应始终为NULL,如果设置,将被忽略。

一个函数,它接受一个指向 C 连续、行为良好的段src,解释为形状为(n_outer, nindarray, nelem)的三维数组的指针,一个指向m_middle整数索引的连续的、行为良好的段indarray的指针,以及一个指向 C 连续、行为良好的段的指针dest,解释为形状为(n_outer, m_middle, nelem)的三维数组。indarray中的索引用于沿着第二维对src进行索引,并将相应的nelem项的块复制到dest中。clipmode(可以取值NPY_RAISENPY_WRAPNPY_CLIP

代码语言:javascript
复制
一个指针,指向一个函数,用于检索`data`指向的开始于`arr`的`n`个元素中最小元素的索引。此函数要求内存段是连续的且行为良好。返回值始终为 0。最小元素的索引存储在`min_ind`中。

`PyArray_Type` 类型对象实现了许多[`Python 对象`](https://docs.python.org/3/c-api/type.html#c.PyTypeObject "(in Python v3.11)")的特性,包括[`tp_as_number`](https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_as_number "(in Python v3.11)")、[`tp_as_sequence`](https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_as_sequence "(in Python v3.11)")、[`tp_as_mapping`](https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_as_mapping "(in Python v3.11)")和[`tp_as_buffer`](https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_as_buffer "(in Python v3.11)")接口。还使用了[`rich comparison`](https://docs.python.org/3/c-api/typeobj.html#c.richcmpfunc "(in Python v3.11)"),以及新式属性查找用于成员([`tp_members`](https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_members "(in Python v3.11)"))和属性([`tp_getset`](https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_getset "(in Python v3.11)"))。`PyArray_Type` 也可以被子类型化。

提示

`tp_as_number`方法使用一种通用方法来调用已注册用于处理操作的任何函数。导入`_multiarray_umath`模块时,它将为所有数组设置相应的 ufunc 数值操作。这个选择可以使用`PyUFunc_ReplaceLoopBySignature`进行更改。还可以使用`PyArray_SetStringFunction`更改`tp_str`和`tp_repr`方法。

### PyUFunc_Type 和 PyUFuncObject

```py
PyUFunc_Type

ufunc 对象是通过创建PyUFunc_Type来实现的。它是一个非常简单的类型,仅实现了基本的 getattribute 行为、打印行为,并具有调用行为,使这些对象可以像函数一样工作。ufunc 背后的基本思想是存储每种支持操作的数据类型的快速一维(向量)循环的引用. 所有这些一维循环都有相同的标识并且是创建新 ufunc 的关键。它们由通用循环代码在适当时调用以实现 N 维功能。还为浮点和复数浮点数组定义了一些通用的 1-d 循环,使您可以使用单个标量函数(例如atanh)来定义一个 ufunc。

代码语言:javascript
复制
type PyUFuncObject

ufunc 的核心是PyUFuncObject,它包含调用执行实际工作的底层 C 代码循环所需的所有信息。虽然这里对其进行了描述以便完整,但应该将其视为 NumPy 的内部部分,并通过PyUFunc_*函数进行操作。该结构的大小可能会随着 NumPy 版本的更改而改变。为确保兼容性:

  • 永远不要声明结构的非指针实例
  • 永远不要执行指针算术
  • 永远不要使用sizeof(PyUFuncObject)

它具有以下结构:

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  nin;
  int  nout;
  int  nargs;
  int  identity;
  PyUFuncGenericFunction  *functions;
  void  **data;
  int  ntypes;
  int  reserved1;
  const  char  *name;
  char  *types;
  const  char  *doc;
  void  *ptr;
  PyObject  *obj;
  PyObject  *userloops;
  int  core_enabled;
  int  core_num_dim_ix;
  int  *core_num_dims;
  int  *core_dim_ixs;
  int  *core_offsets;
  char  *core_signature;
  PyUFunc_TypeResolutionFunc  *type_resolver;
  PyUFunc_LegacyInnerLoopSelectionFunc  *legacy_inner_loop_selector;
  void  *reserved2;
  npy_uint32  *op_flags;
  npy_uint32  *iter_flags;
  /* new in API version 0x0000000D */
  npy_intp  *core_dim_sizes;
  npy_uint32  *core_dim_flags;
  PyObject  *identity_value;
  /* Further private slots (size depends on the NumPy version) */
}  PyUFuncObject; 
代码语言:javascript
复制
int nin

输入参数的数量。

代码语言:javascript
复制
int nout

输出参数的数量。

代码语言:javascript
复制
int nargs

参数的总数(nin + nout)。这个必须小于NPY_MAXARGS

代码语言:javascript
复制
int identity

使用PyUFunc_OnePyUFunc_ZeroPyUFunc_MinusOnePyUFunc_NonePyUFunc_ReorderableNonePyUFunc_IdentityValue来指示此操作的标识。它仅在对空数组进行类似缩减的调用时使用。

代码语言:javascript
复制
void functions(char **args, *dims, *steps, void *extradata)

一个函数指针数组,每一种数据类型都有一个。这个向量循环用于实现底层函数dims[0]次。第一个参数args是一个具有nargs指针的数组,指向行为良好的内存。首先是指向输入参数数据的指针,然后是指向输出参数数据的指针。必须跳过多少字节才能到达序列中的下一个元素由steps数组中的相应条目指定。最后一个参数允许循环接收额外的信息。这通常是为了使单个通用向量循环用于多个函数。在这种情况下,要调用的实际标量函数以extradata的形式传递。此函数指针数组的大小为 ntypes。

代码语言:javascript
复制
void **data

传递给 1 维向量循环的额外数据,如果不需要额外数据,则为NULL。这个 C 数组的大小必须与函数数组相同(即 ntypes)。如果不需要 extra_data,则使用NULL。一些用于 UFuncs 的 C-API 调用只是 1 维向量循环,利用这些额外数据来接收要调用的实际函数的指针。

代码语言:javascript
复制
int ntypes

Ufunc 支持的数据类型数。此数字指定有多少不同的 1 维循环(内置数据类型)可用。

代码语言:javascript
复制
int reserved1

未使用。

代码语言:javascript
复制
char *name

Ufunc 的字符串名称。这个动态用于构建 ufunc 的 doc 属性。

代码语言:javascript
复制
char *types

一个(nargs \times ntypes)的 8 位 type_numbers 数组,其中包含每个支持的(内置)数据类型的函数的类型签名。对于ntypes个函数中的每一个,该数组中相应的一组类型编号显示了如何在 1 维向量循环中解释args参数。这些类型编号不必是相同的类型,支持混合类型的 ufunc。

代码语言:javascript
复制
char *doc

UFunc 的文档。不应包含函数签名,因为这在检索 doc 时动态生成。

代码语言:javascript
复制
void *ptr

任何动态分配的内存。目前,这用于从 python 函数创建的动态 ufunc 中存储类型、数据和名称成员的空间。

代码语言:javascript
复制
*obj

对于从 python 函数动态创建的 ufunc,此成员保存对底层 Python 函数的引用。

代码语言:javascript
复制
*userloops

用户定义的 1 维向量循环的字典(存储为 CObject ptrs),用于用户定义的类型。用户可以为任何用户定义的类型注册循环。它通过类型编号检索。用户定义的类型编号始终大于NPY_USERDEF

代码语言:javascript
复制
int core_enabled

标量 ufunc 的为 0;广义 ufunc 的为 1。

代码语言:javascript
复制
int core_num_dim_ix

签名中的不同核心维度名称数

代码语言:javascript
复制
int *core_num_dims

每个参数的核心维度数

代码语言:javascript
复制
int *core_dim_ixs

展平形式的维度索引;参数k的索引存储在core_dim_ixs[core_offsets[k] : core_offsets[k] + core_numdims[k]]

代码语言:javascript
复制
int *core_offsets

每个参数在core_dim_ixs中的第一个核心维度的位置,相当于 cumsum(core_num_dims)

代码语言:javascript
复制
char *core_signature

核心签名字符串

代码语言:javascript
复制
PyUFunc_TypeResolutionFunc *type_resolver

解析类型并填充一个数组以获取输入和输出的 dtype 的函数

代码语言:javascript
复制
PyUFunc_LegacyInnerLoopSelectionFunc *legacy_inner_loop_selector

自版本 1.22 起弃用:该插槽的一些回退支持存在,但最终将被移除。依赖于此的通用函数最终将必须进行移植。参见NEP 41NEP 43

代码语言:javascript
复制
void *reserved2

对于可能的具有不同签名的未来循环选择器。

代码语言:javascript
复制
op_flags

覆盖每个 ufunc 操作数的默认操作数标志。

代码语言:javascript
复制
iter_flags

覆盖 ufunc 的默认 nditer 标志。

在 API 版本 0x0000000D 中添加

代码语言:javascript
复制
*core_dim_sizes

对于每个不同的核心维度,如果UFUNC_CORE_DIM_SIZE_INFERRED0,则可能为冻结大小

代码语言:javascript
复制
*core_dim_flags

对于每个不同的核心维度,一组标志(UFUNC_CORE_DIM_CAN_IGNOREUFUNC_CORE_DIM_SIZE_INFERRED)

代码语言:javascript
复制
*identity_value

缩减的身份,当PyUFuncObject.identity等于PyUFunc_IdentityValue时。

代码语言:javascript
复制
UFUNC_CORE_DIM_CAN_IGNORE

如果维度名称以?结尾

代码语言:javascript
复制
UFUNC_CORE_DIM_SIZE_INFERRED

如果维度大小将根据操作数确定而不是来自冻结签名

PyArrayIter_Type 和 PyArrayIterObject
代码语言:javascript
复制
PyArrayIter_Type

这是一个迭代器对象,可以轻松地循环遍历 N 维数组。它是从 ndarray 的 flat 属性返回的对象。它还广泛地用于实现内部,以便循环遍历 N 维数组。实现了 tp_as_mapping 接口,以便可以索引迭代器对象(使用 1-d 索引),并且通过 tp_methods 表实现了一些方法。这个对象实现了 next 方法,并且可以在 Python 中的任何地方使用迭代器。

代码语言:javascript
复制
type PyArrayIterObject

PyArrayIter_Type对象对应的 C 结构是PyArrayIterObjectPyArrayIterObject用于跟踪 N 维数组中的指针。它包含用于快速遍历数组的相关信息。指针可以通过三种基本方式进行调整:1)以 C 样式的连续方式前进到数组中的“下一个”位置,2)前进到数组中的任意 N 维坐标,3)前进到数组中的任意一维索引。PyArrayIterObject结构的成员用于进行这些计算。迭代器对象保留有关数组的自己的维度和跨度信息。这可根据需要进行调整,以进行“广播”,或仅在特定维度上循环。

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  nd_m1;
  npy_intp  index;
  npy_intp  size;
  npy_intp  coordinates[NPY_MAXDIMS];
  npy_intp  dims_m1[NPY_MAXDIMS];
  npy_intp  strides[NPY_MAXDIMS];
  npy_intp  backstrides[NPY_MAXDIMS];
  npy_intp  factors[NPY_MAXDIMS];
  PyArrayObject  *ao;
  char  *dataptr;
  npy_bool  contiguous;
}  PyArrayIterObject; 
代码语言:javascript
复制
int nd_m1

(N-1),其中(N)是底层数组中的维数。

代码语言:javascript
复制
index

到数组的当前一维索引。

代码语言:javascript
复制
size

底层数组的总大小。

代码语言:javascript
复制
*coordinates

到数组的(N) -维索引。

代码语言:javascript
复制
*dims_m1

每个维度中数组大小减 1。

代码语言:javascript
复制
*strides

数组的跨度。在每个维度中跳到下一个元素需要多少字节。

代码语言:javascript
复制
*backstrides

从维度末尾跳回到开头需要多少字节。注意backstrides[k] == strides[k] * dims_m1[k],但它被存储在这里作为一种优化。

代码语言:javascript
复制
*factors

该数组用于从一维索引计算 N 维索引。它包含所需的维度的乘积。

代码语言:javascript
复制
*ao

指向此迭代器被创建以代表的基础 ndarray 的指针。

代码语言:javascript
复制
char *dataptr

此成员指向由索引指示的 ndarray 中的一个元素。

代码语言:javascript
复制
contiguous

如果底层数组是NPY_ARRAY_C_CONTIGUOUS,则此标志为 true。它用于在可能的情况下简化计算。

如何在 C 级别上使用数组迭代器在后续章节中有更详细的解释。通常情况下,您不需要关心迭代器对象的内部结构,只需通过宏PyArray_ITER_NEXT (it)、PyArray_ITER_GOTO (it, dest)或者PyArray_ITER_GOTO1D (it, index)来与之交互即可,所有这些宏要求参数it是 PyArrayIterObject*。

PyArrayMultiIter_Type 和 PyArrayMultiIterObject
代码语言:javascript
复制
PyArrayMultiIter_Type

这种类型提供了一种封装广播概念的迭代器。它允许将(N)个数组一起广播,使得循环按照广播数组的 C 风格连续方式进行。相应的 C 结构是PyArrayMultiIterObject,其内存布局必须从任何传递给PyArray_Broadcast (obj)函数的对象obj开始。通过调整数组迭代器执行广播,使得每个迭代器表示广播的形状和大小,但其步幅调整为每次迭代中使用数组的正确元素。

代码语言:javascript
复制
type PyArrayMultiIterObject
代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  numiter;
  npy_intp  size;
  npy_intp  index;
  int  nd;
  npy_intp  dimensions[NPY_MAXDIMS];
  PyArrayIterObject  *iters[NPY_MAXDIMS];
}  PyArrayMultiIterObject; 
代码语言:javascript
复制
int numiter

需要广播到相同形状的数组的数量。

代码语言:javascript
复制
size

广播的总大小。

代码语言:javascript
复制
index

广播结果的当前(1-D)索引。

代码语言:javascript
复制
int nd

广播结果中的维数。

代码语言:javascript
复制
*dimensions

广播结果的形状(仅使用nd个插槽)。

代码语言:javascript
复制
**iters

一个迭代器对象数组,其中包含要合并广播的数组的迭代器。返回时,这些迭代器已调整为进行广播。

PyArrayNeighborhoodIter_Type 和 PyArrayNeighborhoodIterObject
代码语言:javascript
复制
PyArrayNeighborhoodIter_Type

这是一个迭代器对象,它可以轻松地在 N 维邻域上循环。

代码语言:javascript
复制
type PyArrayNeighborhoodIterObject

PyArrayNeighborhoodIter_Type对象对应的 C 结构是PyArrayNeighborhoodIterObject

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  nd_m1;
  npy_intp  index,  size;
  npy_intp  coordinates[NPY_MAXDIMS]
  npy_intp  dims_m1[NPY_MAXDIMS];
  npy_intp  strides[NPY_MAXDIMS];
  npy_intp  backstrides[NPY_MAXDIMS];
  npy_intp  factors[NPY_MAXDIMS];
  PyArrayObject  *ao;
  char  *dataptr;
  npy_bool  contiguous;
  npy_intp  bounds[NPY_MAXDIMS][2];
  npy_intp  limits[NPY_MAXDIMS][2];
  npy_intp  limits_sizes[NPY_MAXDIMS];
  npy_iter_get_dataptr_t  translate;
  npy_intp  nd;
  npy_intp  dimensions[NPY_MAXDIMS];
  PyArrayIterObject*  _internal_iter;
  char*  constant;
  int  mode;
}  PyArrayNeighborhoodIterObject; 
PyArrayFlags_Type 和 PyArrayFlagsObject
代码语言:javascript
复制
PyArrayFlags_Type

当从 Python 检索 flags 属性时,会构造一个特殊的内置对象的此类型。这种特殊的类型使得通过访问它们作为属性或者假定对象是一个以标志名称为条目的字典而访问它们来更容易地处理不同的标志。

代码语言:javascript
复制
type PyArrayFlagsObject
代码语言:javascript
复制
typedef  struct  PyArrayFlagsObject  {
  PyObject_HEAD
  PyObject  *arr;
  int  flags;
}  PyArrayFlagsObject; 
标量数组类型

数组中可能出现的不同内置数据类型都有对应的 Python 类型。其中大多数类型只是对应的 C 语言数据类型的简单封装。这些类型在 C 语言中的名称为 Py{TYPE}ArrType_Type,其中 {TYPE} 可以是

BoolByteShortIntLongLongLongUByteUShortUIntULongULongLongHalfFloatDoubleLongDoubleCFloatCDoubleCLongDoubleStringUnicodeVoidObject

这些类型名称属于 C-API 的一部分,因此可以在扩展 C 代码中创建。还有一个 PyIntpArrType_TypePyUIntpArrType_Type,它们是平台上可以保存指针的整数类型的简单替代品。这些标量对象的结构对 C 代码不可见。函数 PyArray_ScalarAsCtype (…) 可以用于从数组标量中提取 C 类型值,而函数 PyArray_Scalar (…) 可以用于从 C 值构造一个数组标量。

- PyArray_TypePyArrayObject
代码语言:javascript
复制
PyArray_Type

ndarray 的 Python 类型是PyArray_Type。在 C 中,每个 ndarray 都是一个指向 PyArrayObject 结构的指针。这个结构的 ob_type 成员包含一个指向 PyArray_Type 类型对象的指针。

代码语言:javascript
复制
type PyArrayObject
代码语言:javascript
复制
type NPY_AO

PyArrayObject C 结构包含数组的所有必要信息。所有 ndarray(及其子类)的实例都具有这一结构。为了未来的兼容性,应该使用提供的宏来访问这些结构成员。如果需要更短的名称,那么可以使用 NPY_AO(已弃用),它被定义为等同于 PyArrayObject。直接访问结构字段已被弃用。请改用 PyArray_*(arr) 形式。从 NumPy 1.20 开始,此结构的大小不被认为是 NumPy ABI 的一部分(请参见成员列表末尾的注释)。

代码语言:javascript
复制
typedef  struct  PyArrayObject  {
  PyObject_HEAD
  char  *data;
  int  nd;
  npy_intp  *dimensions;
  npy_intp  *strides;
  PyObject  *base;
  PyArray_Descr  *descr;
  int  flags;
  PyObject  *weakreflist;
  /* version dependent private members */
}  PyArrayObject; 
代码语言:javascript
复制
PyObject_HEAD

这适用于所有 Python 对象。它至少包含一个引用计数成员( ob_refcnt )和一个类型对象指针( ob_type )。(如果使用特殊选项编译 Python,可能还有其他成员,请参见 Python 源代码树中的 Include/object.h 获取更多信息。)ob_type 成员指向一个 Python 类型对象。

代码语言:javascript
复制
char *data

通过 PyArray_DATA 可以访问到这个数据成员,它是数组的第一个元素的指针。这个指针可以(通常应该)被重新解释为数组的数据类型。

代码语言:javascript
复制
int nd

为此数组提供维数的整数。当 nd 为 0 时,有时称该数组为秩为 0 的数组。这样的数组具有未定义的维度和步幅,并且无法访问。宏 PyArray_NDIMndarraytypes.h 中定义,指向此数据成员。NPY_MAXDIMS 是任何数组的最大维数。

代码语言:javascript
复制
*dimensions

一个提供每个维度的形状的整数数组,只要 nd (\geq) 1. 该整数始终足够大,以容纳平台上的指针,因此维度大小仅受内存限制。PyArray_DIMS 是与此数据成员关联的宏。

代码语言:javascript
复制
*strides

为每个维度提供一个整数数组,指定必须跳过多少字节才能到达该维度中的下一个元素。与宏PyArray_STRIDES 相关。

代码语言:javascript
复制
*base

PyArray_BASE 指向,此成员用于保存指向与此数组相关的另一个 Python 对象的指针。有两种用法:

  • 如果该数组不拥有自己的内存,则 base 指向拥有它的 Python 对象(也许是另一个数组对象)。
  • 如果此数组设置了NPY_ARRAY_WRITEBACKIFCOPY 标志,则此数组是“行为不端”数组的工作副本。

当调用 PyArray_ResolveWritebackIfCopy 时,base 指向的数组将使用此数组的内容进行更新。

代码语言:javascript
复制
*descr

指向数据类型描述符对象的指针(见下文)。数据类型描述符对象是一种新的内置类型的实例,允许对内存进行通用描述。对于支持的每种数据类型都有一个描述符结构。此描述符结构包含有关类型的有用信息以及实现特定功能的函数指针表的指针。正如名称所示,它与宏PyArray_DESCR 相关联。

代码语言:javascript
复制
int flags

由宏PyArray_FLAGS 指向的,这个数据成员表示标志,指示由 data 指向的内存应如何解释。可能的标志有NPY_ARRAY_C_CONTIGUOUSNPY_ARRAY_F_CONTIGUOUSNPY_ARRAY_OWNDATANPY_ARRAY_ALIGNEDNPY_ARRAY_WRITEABLENPY_ARRAY_WRITEBACKIFCOPY

代码语言:javascript
复制
*weakreflist

此成员允许数组对象具有弱引用(使用 weakref 模块)。

注意

进一步的成员被视为私有和版本相关的。如果结构的大小对您的代码很重要,则必须特别小心。当这一点是相关的时候可能的用例是在 C 中进行子类化。如果您的代码依赖于sizeof(PyArrayObject)是常量,您必须在导入时添加以下检查:

代码语言:javascript
复制
if  (sizeof(PyArrayObject)  <  PyArray_Type.tp_basicsize)  {
  PyErr_SetString(PyExc_ImportError,
  "Binary incompatibility with NumPy, must recompile/update X.");
  return  NULL;
} 

为了确保您的代码不必为特定的 NumPy 版本编译,您可以添加一个常量,为 NumPy 的更改留出空间。一个确保与任何未来 NumPy 版本兼容的解决方案需要使用运行时计算偏移和分配大小。

PyArrayDescr_Type 和 PyArray_Descr
代码语言:javascript
复制
PyArrayDescr_Type

PyArrayDescr_Type是用于描述如何解释组成数组的字节的数据类型描述符对象的内置类型。有 21 个静态定义的PyArray_Descr对象用于内置数据类型。虽然它们参与引用计数,但它们的引用计数永远不应该达到零。还有一个动态的用户定义的PyArray_Descr对象表也在维护中。一旦数据类型描述符对象被“注册”,就不应该被释放。函数PyArray_DescrFromType(…)可以用于从枚举类型编号(内置或用户定义的)检索PyArray_Descr对象。

代码语言:javascript
复制
type PyArray_Descr

PyArray_Descr结构位于PyArrayDescr_Type的核心。虽然这里对其进行了描述以保持完整性,但应该将其视为 NumPy 的内部结构,并通过PyArrayDescr_*PyDataType*函数和宏来操作。此结构的大小可能会随 NumPy 版本的变化而变化。为了确保兼容性:

  • 永远不要声明结构的非指针实例
  • 永远不要进行指针算术运算
  • 永远不要使用 sizeof(PyArray_Descr)

它具有以下结构:

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  PyTypeObject  *typeobj;
  char  kind;
  char  type;
  char  byteorder;
  char  flags;
  int  type_num;
  int  elsize;
  int  alignment;
  PyArray_ArrayDescr  *subarray;
  PyObject  *fields;
  PyObject  *names;
  PyArray_ArrFuncs  *f;
  PyObject  *metadata;
  NpyAuxData  *c_metadata;
  npy_hash_t  hash;
}  PyArray_Descr; 
代码语言:javascript
复制
*typeobj

指向与此数组元素对应的 Python 类型的类型对象的指针。对于内置类型,这指向相应的数组标量。对于用户定义的类型,这应该指向用户定义的类型对象。这个类型对象可以继承自数组标量,也可以不继承。如果它不继承自数组标量,则flags成员中应设置NPY_USE_GETITEMNPY_USE_SETITEM标志。

代码语言:javascript
复制
char kind

表示数组种类的字符代码(使用数组接口类型字符串表示法)。‘b’表示布尔,‘i’表示有符号整数,‘u’表示无符号整数,‘f’表示浮点数,‘c’表示复数浮点数,‘S’表示 8 位以零结尾的字节,‘U’表示 32 位/字符的 Unicode 字符串,‘V’表示任意。

代码语言:javascript
复制
char type

表示数据类型的传统字符代码。

代码语言:javascript
复制
char byteorder

表示字节顺序的字符:‘>’(大端)、‘<’(小端)、‘=’(本地)、‘|’(不相关,忽略)。所有内置数据类型的字节顺序都是‘=’。

代码语言:javascript
复制
char flags

一个数据类型位标志,确定数据类型是否表现出对象数组的行为。该成员中的每个位都是一个标志,命名为:

  • NPY_ITEM_REFCOUNT
  • NPY_ITEM_HASOBJECT
  • NPY_LIST_PICKLE
  • NPY_ITEM_IS_POINTER
  • NPY_NEEDS_INIT
  • NPY_NEEDS_PYAPI
  • NPY_USE_GETITEM
  • NPY_USE_SETITEM
  • NPY_FROM_FIELDS
  • NPY_OBJECT_DTYPE_FLAGS
代码语言:javascript
复制
int type_num

一个唯一标识数据类型的数字。对于新数据类型,当数据类型被注册时,会分配这个数字。

代码语言:javascript
复制
int elsize

对于始终大小相同的数据类型(例如 long),这保存数据类型的大小。对于灵活的数据类型,其中不同的数组可以具有不同的元素大小,这应为 0。

代码语言:javascript
复制
int alignment

为此数据类型提供对齐信息的数字。具体来说,它显示了编译器将该类型的项目放置在起始为 char 的 2 元结构中的距离:offsetof(struct {char c; type v;}, v)

代码语言:javascript
复制
*subarray

如果这是非 NULL,那么这个数据类型描述符是另一个数据类型描述符的 C 风格连续数组。换句话说,这个描述符描述的每个元素实际上都是另一个基本描述符的数组。这在作为另一个数据类型描述符中的字段的数据类型描述符时最有用。如果这是非 NULL,则 fields 成员应为 NULL(但基本描述符的 fields 成员可以是非 NULL)。

代码语言:javascript
复制
type PyArray_ArrayDescr
代码语言:javascript
复制
typedef  struct  {
  PyArray_Descr  *base;
  PyObject  *shape;
}  PyArray_ArrayDescr; 
代码语言:javascript
复制
*base

基础类型的数据类型描述符对象。

代码语言:javascript
复制
*shape

作为 Python 元组的子数组的形状(始终是 C 风格连续的)。

代码语言:javascript
复制
*fields

如果这是非 NULL,则此数据类型描述符具有由 Python 字典描述的字段,其键是名称(如果给定也是标题),其值是描述字段的元组。回想一下,数据类型描述符总是描述一组固定长度的字节。字段是该总体、固定长度的集合的命名子区域。字段由另一个数据类型描述符和字节偏移量组成的元组描述。可选地,元组可以包含一个标题,通常是 Python 字符串。这些元组被放置在此字典中,键为名称(如果给定也是标题)。

代码语言:javascript
复制
*names

一个有序的字段名称元组。如果未定义字段,则为 NULL。

代码语言:javascript
复制
*f

指向包含类型需要实现内部功能的函数的结构体指针。这些函数与后面描述的通用函数(ufuncs)不是同一种东西。它们的签名可以任意变化。

代码语言:javascript
复制
*metadata

关于此数据类型的元数据。

代码语言:javascript
复制
*c_metadata

特定于特定数据类型的 C 实现的元数据。添加于 NumPy 1.7.0。

代码语言:javascript
复制
type npy_hash_t
代码语言:javascript
复制
*hash

目前未使用。保留以缓存散列值的未来使用。

代码语言:javascript
复制
NPY_ITEM_REFCOUNT

表明此数据类型的项目必须进行引用计数(使用Py_INCREFPy_DECREF)。

代码语言:javascript
复制
NPY_ITEM_HASOBJECT

NPY_ITEM_REFCOUNT相同。

代码语言:javascript
复制
NPY_LIST_PICKLE

表示此数据类型的数��必须在 pickling 之前转换为列表。

代码语言:javascript
复制
NPY_ITEM_IS_POINTER

表示项目是指向其他数据类型的指针。

代码语言:javascript
复制
NPY_NEEDS_INIT

表示此数据类型的内存在创建时必须初始化(设置为 0)。

代码语言:javascript
复制
NPY_NEEDS_PYAPI

表明此数据类型在访问时需要 Python C-API(因此如果需要数组访问,则不要放弃 GIL)。

代码语言:javascript
复制
NPY_USE_GETITEM

在数组访问中,使用f->getitem函数指针,而不是标准的转换为数组标量。如果没有定义与数据类型相配套的数组标量,则必须使用。

代码语言:javascript
复制
NPY_USE_SETITEM

从数组标量创建 0 维数组时,请使用f->setitem,而不是标准的从数组标量复制。如果没有定义与数据类型相匹配的数组标量,则必须使用。

代码语言:javascript
复制
NPY_FROM_FIELDS

如果这些位在数据类型的任何字段中设置,那么这些位就会继承自父数据类型。当前(NPY_NEEDS_INIT | NPY_LIST_PICKLE | NPY_ITEM_REFCOUNT | NPY_NEEDS_PYAPI)。

代码语言:javascript
复制
NPY_OBJECT_DTYPE_FLAGS

为对象数据类型设置的位:(NPY_LIST_PICKLE | NPY_USE_GETITEM | NPY_ITEM_IS_POINTER | NPY_ITEM_REFCOUNT | NPY_NEEDS_INIT | NPY_NEEDS_PYAPI)。

代码语言:javascript
复制
int PyDataType_FLAGCHK( *dtype, int flags)

如果数据类型对象上设置了给定标志,则返回 true。

代码语言:javascript
复制
int PyDataType_REFCHK( *dtype)

等同于PyDataType_FLAGCHKdtype, NPY_ITEM_REFCOUNT)。

代码语言:javascript
复制
type PyArray_ArrFuncs

实现内部功能的函数。并非所有这些函数指针都必须为给定类型定义。所需成员包括nonzerocopyswapcopyswapnsetitemgetitemcast。假定这些为非NULL,而NULL条目将导致程序崩溃。其他功能可能为NULL,这只会减少该数据类型的功能。(另外,如果在注册用户定义的数据类型时NULL,则nonzero函数将用默认函数填充)。

代码语言:javascript
复制
typedef  struct  {
  PyArray_VectorUnaryFunc  *cast[NPY_NTYPES];
  PyArray_GetItemFunc  *getitem;
  PyArray_SetItemFunc  *setitem;
  PyArray_CopySwapNFunc  *copyswapn;
  PyArray_CopySwapFunc  *copyswap;
  PyArray_CompareFunc  *compare;
  PyArray_ArgFunc  *argmax;
  PyArray_DotFunc  *dotfunc;
  PyArray_ScanFunc  *scanfunc;
  PyArray_FromStrFunc  *fromstr;
  PyArray_NonzeroFunc  *nonzero;
  PyArray_FillFunc  *fill;
  PyArray_FillWithScalarFunc  *fillwithscalar;
  PyArray_SortFunc  *sort[NPY_NSORTS];
  PyArray_ArgSortFunc  *argsort[NPY_NSORTS];
  PyObject  *castdict;
  PyArray_ScalarKindFunc  *scalarkind;
  int  **cancastscalarkindto;
  int  *cancastto;
  PyArray_FastClipFunc  *fastclip;  /* deprecated */
  PyArray_FastPutmaskFunc  *fastputmask;  /* deprecated */
  PyArray_FastTakeFunc  *fasttake;  /* deprecated */
  PyArray_ArgFunc  *argmin;
}  PyArray_ArrFuncs; 

在描述函数指针时使用了行为良好的段的概念。 行为良好的段是指与数据类型的本机机器字节顺序对齐的段。 nonzerocopyswapcopyswapngetitemsetitem 函数可以(并且必须)处理不规范的数组。 其他函数需要行为良好的内存段。

代码语言:javascript
复制
void cast(void *from, void *to, n, void *fromarr, void *toarr)

用于将当前类型转换为所有其他内置类型的函数指针数组。 每个函数将由 from 指向的连续、对齐且未交换的缓冲区转换为由 to 指向的连续、对齐且未交换的缓冲区。 要转换的项目数由 n 给出,并且参数 fromarrtoarr 被解释为灵活数组的 PyArrayObjects 以获取 itemsize 信息。

代码语言:javascript
复制
*getitem(void *data, void *arr)

指向从由 data 指向的数组对象 arr 的单个元素返回标准 Python 对象的函数的指针。 该函数必须能够正确处理“不规范”(未对齐和/或已交换)的数组。

代码语言:javascript
复制
int setitem( *item, void *data, void *arr)

指向将 Python 对象 item 设置到数组 arr 中由 data 指向位置的函数的指针。 该函数处理“不规范”的数组。 如果成功,则返回零,否则返回负一(并设置 Python 错误)。

代码语言:javascript
复制
void copyswapn(void *dest, dstride, void *src, sstride, n, int swap, void *arr)
代码语言:javascript
复制
void copyswap(void *dest, void *src, int swap, void *arr)

这些成员都是指向从 src 复制数据到 dest 并在需要时交换的函数的指针。 arr 的值仅用于灵活(NPY_STRINGNPY_UNICODENPY_VOID)数组(并从 arr->descr->elsize 获取)。 第二个函数复制单个值,而第一个函数则使用提供的步幅循环 n 个值。 这些函数可以处理不规范的 src 数据。 如果 src 为 NULL,则不执行复制。 如果 swap 为 0,则不进行字节交换。 假定 destsrc 不重叠。 如果它们重叠,则首先使用 memmove(…)后跟 NULL 值的 src 进行 copyswap(n)

代码语言:javascript
复制
int compare(const void *d1, const void *d2, void *arr)

指向比较数组 arr 中由 d1d2 指向的两个元素的函数的指针。 此函数需要行为良好的(对齐且未交换)数组。 如果 * d1 > * d2,则返回值为 1,如果 * d1 == * d2,则返回值为 0,如果 * d1 < * d2,则返回值为 -1。 用于灵活数组的数组对象 arr 用于检索 itemsize 和字段信息。

代码语言:javascript
复制
int argmax(void *data, n, *max_ind, void *arr)

指向从由 data 指向的数组中从指向的元素开始的 n 个元素中检索最大索引的函数的指针。 此函数要求内存段是连续且行为良好的。 返回值始终为 0。 最大元素的索引在 max_ind 中返回。

代码语言:javascript
复制
void dotfunc(void *ip1, is1, void *ip2, is2, void *op, n, void *arr)

指向函数的指针,将两个n长度序列相乘,相加,并将结果放置在arrop指向的元素中。两个序列的起始点由ip1ip2指向。要进入每个序列的下一个元素,分别需要跳过is1is2 字节。此函数需要良好行为的内存(尽管不一定是连续的)。

代码语言:javascript
复制
int scanfunc(FILE *fd, void *ip, void *arr)

指向函数的指针,从文件描述符fd中扫描(类似于 scanf)相应类型的一个元素到由ip指向的数组内存中。假定数组良好行为。最后一个参数arr是要扫描到的数组。返回成功分配的接收参数的数量(如果在分配第一个接收参数之前发生匹配失败,则可能为零),或者如果在分配第一个接收参数之前发生输入失败则返回 EOF。此函数应在不持有 Python GIL 的情况下调用,并且在报告错误时必须抓取它。

代码语言:javascript
复制
int fromstr(char *str, void *ip, char **endptr, void *arr)

指向函数的指针,将由str指向的字符串转换为相应类型的一个元素,并将其放置在由ip指向的内存位置。转换完成后,*endptr指向字符串的剩余部分。最后一个参数arrip指向的数组(对于可变大小数据类型需要)。成功返回 0,失败返回-1。需要一个良好行为的数组。此函数应在不持有 Python GIL 的情况下调用,并且在报告错误时必须抓取它。

代码语言:javascript
复制
nonzero(void *data, void *arr)

指向函数的指针,如果data指向的arr的项非零,则返回 TRUE。该函数可处理不良行为的数组。

代码语言:javascript
复制
void fill(void *data, length, void *arr)

指向函数的指针,用于将给定长度的连续数组填充到数据中。数组的前两个元素必须已经填充。从这两个值中,将计算一个增量,然后通过重复添加此计算出的增量来计算从第 3 个项目到末尾的值。数据缓冲区必须良好行为。

代码语言:javascript
复制
void fillwithscalar(void *buffer, length, void *value, void *arr)

指向函数的指针,用给定的value填充给定length的连续buffer。最后一个参数是需要获取变长数组的项大小。

代码语言:javascript
复制
int sort(void *start, length, void *arr)

一组函数指针的数组,指向特定的排序算法。使用键(到目前为止已定义NPY_QUICKSORTNPY_HEAPSORTNPY_MERGESORT)获得特定的排序算法。这些排序是就地完成的,假设数据是连续且对齐的。

代码语言:javascript
复制
int argsort(void *start, *result, length, void *arr)

一组函数指针的数组,用于这种数据类型的排序算法。与 sort 相同的排序算法可用。产生排序的索引将返回到result(必须初始化为 0 到length-1的索引)。

代码语言:javascript
复制
*castdict

可以为NULL,也可以是包含用户定义数据类型的低级转换函数的字典。每个函数都包装在PyCapsule*中,并以数据类型编号为键。

代码语言:javascript
复制
scalarkind( *arr)

一个确定此类型标量应该如何解释的函数。该参数为NULL或包含数据的零维数组(如果需要确定标量的类型)。返回值必须为类型NPY_SCALARKIND

代码语言:javascript
复制
int **cancastscalarkindto

可以为NULL,也可以是NPY_NSCALARKINDS指针数组。这些指针可以是NULL,也可以是指向整数数组的指针(以NPY_NOTYPE结尾),指示此指定类型的标量可以安全转换的数据类型(通常意味着不会失去精度)。

代码语言:javascript
复制
int *cancastto

可以为NULL,也可以是一个整数数组(以NPY_NOTYPE结尾),指示此数据类型可以安全转换的数据类型(通常意味着不会失去精度)。

代码语言:javascript
复制
void fastclip(void *in, n_in, void *min, void *max, void *out)

自 1.17 版本起已弃用:当np.clip时,使用此函数会引发弃用警告。而不是使用此函数,数据类型必须使用PyUFunc_RegisterLoopForDescr将自定义循环附加到np.core.umath.clipnp.minimumnp.maximum

自 1.19 版本起已弃用:设置此函数已被弃用,应该始终为NULL,如果设置了,将被忽略。

一个从in中读取n_in个项目,并在minmax指向的限制内写入out的值的函数,如果读取的值在minmax指向的限制内,或者在外部,则相应的限制。内存段必须是连续的且表现良好,minmax可以为NULL,但不能同时为NULL

代码语言:javascript
复制
void fastputmask(void *in, void *mask, n_in, void *values, nv)

自 1.19 版本起已弃用:设置此函数已被弃用,应该始终为NULL,如果设置了,将被忽略。

一个使用指针in指向一个包含n_in个项目的数组,指针mask指向一个包含n_in个布尔值的数组,以及指针vals指向一个包含nv个项目的数组的函数。将vals中的项目复制到in中,无论mask中的值是否为非零,在nv < n_in的情况下需要按需平铺vals。所有数组必须是连续的且表现良好。

代码语言:javascript
复制
void fasttake(void *dest, void *src, *indarray, nindarray, n_outer, m_middle, nelem, clipmode)

自 1.19 版本起已弃用:设置此函数已被弃用,应该始终为NULL,如果设置了,将被忽略。

一个函数,它接受指向 C 连续、行为良好段的指针src,解释为形状为(n_outer, nindarray, nelem)的 3 维数组,指向indarray指针到m_middle整数索引的连续、行为良好段,以及指向 C 连续、行为良好段的指针dest,解释为形状为(n_outer, m_middle, nelem)的 3 维数组。indarray中的索引用于沿第二维索引src,并将nelem项的相应块复制到destclipmode(可以取值NPY_RAISENPY_WRAPNPY_CLIP)确定小于 0 或大于nindarray的索引将如何处理。

代码语言:javascript
复制
int argmin(void *data, n, *min_ind, void *arr)

指针指向一个函数,该函数检索数组arr中从指向data的元素开始的n个元素中最小的索引。此函数要求内存段是连续且行为良好。返回值始终为 0。最小元素的索引在min_ind中返回。

PyArray_Type类型对象实现了许多Python 对象的特性,包括tp_as_numbertp_as_sequencetp_as_mappingtp_as_buffer接口。还使用了rich comparison以及成员(tp_members)和属性(tp_getset)的新式属性查找。PyArray_Type也可以被子类化。

提示

tp_as_number 方法使用通用方法调用已注册用于处理操作的函数。当导入_multiarray_umath模块时,它将所有数组的数字操作设置为相应的 ufunc。可以使用PyUFunc_ReplaceLoopBySignature更改此选择,也可以使用PyArray_SetStringFunction改变tp_strtp_repr方法。

PyUFunc_Type 和 PyUFuncObject
代码语言:javascript
复制
PyUFunc_Type

ufunc 对象是通过创建PyUFunc_Type来实现的。这是一种非常简单的类型,仅实现了基本的 getattribute 行为、打印行为,并具有调用行为,允许这些对象像函数一样运行。ufunc 的基本思想是持有对支持该操作的每种数据类型的快速 1 维(向量)循环的引用。这些一维循环都具有相同的签名,并且是创建新 ufunc 的关键。它们由通用循环代码在适当的时候调用,以实现 N 维函数。还为浮点和复数浮点数组定义了一些通用的 1-d 循环,允许您使用单个标量函数定义 ufunc(例如atanh)。

代码语言:javascript
复制
type PyUFuncObject

ufunc 的核心是PyUFuncObject,它包含调用执行实际工作的基础 C 代码循环所需的所有信息。虽然这里描述了完整的内容,但它应被视为 NumPy 的内部内容,并通过PyUFunc_*函数来操作。该结构的大小可能会因 NumPy 的不同版本而发生变化。为了确保兼容性:

  • 永远不要声明结构的非指针实例
  • 永远不要执行指针算术
  • 永远不要使用sizeof(PyUFuncObject)

它具有以下结构:

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  nin;
  int  nout;
  int  nargs;
  int  identity;
  PyUFuncGenericFunction  *functions;
  void  **data;
  int  ntypes;
  int  reserved1;
  const  char  *name;
  char  *types;
  const  char  *doc;
  void  *ptr;
  PyObject  *obj;
  PyObject  *userloops;
  int  core_enabled;
  int  core_num_dim_ix;
  int  *core_num_dims;
  int  *core_dim_ixs;
  int  *core_offsets;
  char  *core_signature;
  PyUFunc_TypeResolutionFunc  *type_resolver;
  PyUFunc_LegacyInnerLoopSelectionFunc  *legacy_inner_loop_selector;
  void  *reserved2;
  npy_uint32  *op_flags;
  npy_uint32  *iter_flags;
  /* new in API version 0x0000000D */
  npy_intp  *core_dim_sizes;
  npy_uint32  *core_dim_flags;
  PyObject  *identity_value;
  /* Further private slots (size depends on the NumPy version) */
}  PyUFuncObject; 
代码语言:javascript
复制
int nin

输入参数的数量。

代码语言:javascript
复制
int nout

输出参数的数量。

代码语言:javascript
复制
int nargs

参数的总数(nin + nout)。这必须小于NPY_MAXARGS

代码语言:javascript
复制
int identity

要么PyUFunc_OnePyUFunc_ZeroPyUFunc_MinusOnePyUFunc_NonePyUFunc_ReorderableNonePyUFunc_IdentityValue用于指示该操作的身份。它仅在对空数组进行类似于 reduce 的调用时使用。

代码语言:javascript
复制
void functions(char **args, *dims, *steps, void *extradata)

一个函数指针数组—每种 ufunc 支持的数据类型都有一个。这是被调用以实现底层函数的向量循环,dims [0]次。第一个参数args是一个包含nargs指针的行为内存数组。首先是输入参数的数据指针,然后是输出参数的数据指针。必须跳过多少字节才能到达序列中的下一个元素是由steps数组中的相应条目指定的。最后一个参数允许循环接收额外的信息。这通常用于一个通用的向量循环可以用于多个函数的情况。在这种情况下,要调用的实际标量函数作为extradata传递进来。该函数指针数组的大小为 ntypes。

代码语言:javascript
复制
void **data

要传递给 1-d 向量循环的额外数据,如果不需要额外数据则为 NULL。这个 C 数组必须与函数数组的大小相同( ntypes)。如果不需要额外数据,则使用 NULL。对于 UFuncs 的几个 C-API 调用只是使用这些额外数据的 1-d 向量循环,以接收指向要调用的实际函数的指针。

代码语言:javascript
复制
int ntypes

ufunc 支持的数据类型数量。这个数字指定了内置数据类型的多少不同的 1-d 循环可用。

代码语言:javascript
复制
int reserved1

未使用。

代码语言:javascript
复制
char *name

ufunc 的字符串名称。这在动态构建 ufuncs 的 __doc__ 属性时使用。

代码语言:javascript
复制
char *types

一个 (nargs \times ntypes) 的 8 位 type_numbers 数组,其中包含函数对于每个支持的(内置)数据类型的类型签名。对于每个 ntypes 函数,该数组中相应的类型编号集显示了 1-d 向量循环中 args 参数应该如何解释。这些类型编号不必是相同的类型,支持混合类型的 ufuncs。

代码语言:javascript
复制
char *doc

ufunc 的文档。不应该包含函数签名,因为在检索 __doc__ 时会动态生成。

代码语言:javascript
复制
void *ptr

任何动态分配的内存。目前,这用于从 Python 函数创建动态 ufuncs,用于存储类型、数据和名称成员的空间。

代码语言:javascript
复制
*obj

对于从 Python 函数动态创建的 ufuncs,这个成员保存对底层 Python 函数的引用。

代码语言:javascript
复制
*userloops

用户定义的 1-d 向量循环的字典(存储为 CObject ptrs)用于用户定义的类型。用户可以为任何用户定义的类型注册一个循环。它通过类型编号检索。用户定义的类型编号始终大于NPY_USERDEF

代码语言:javascript
复制
int core_enabled

标量 ufunc 为 0;广义 ufunc 为 1

代码语言:javascript
复制
int core_num_dim_ix

签名中核心维度名称的不同个数

代码语言:javascript
复制
int *core_num_dims

每个参数的核心维度的数量

代码语言:javascript
复制
int *core_dim_ixs

以扁平化的形式存储的维度索引;第 k 个参数的索引存储在 core_dim_ixs[core_offsets[k] : core_offsets[k] + core_numdims[k]]

代码语言:javascript
复制
int *core_offsets

每个参数中第一个核心维度的位置在 core_dim_ixs 中,等同于累加和(core_num_dims)

代码语言:javascript
复制
char *core_signature

核心签名字符串

代码语言:javascript
复制
PyUFunc_TypeResolutionFunc *type_resolver

解析类型并填充输入和输出的 dtypes 的函数

代码语言:javascript
复制
PyUFunc_LegacyInnerLoopSelectionFunc *legacy_inner_loop_selector

从版本 1.22 起弃用:这个插槽存在某些后备支持,但最终将被移除。依赖于此的通用函数最终将必须迁移。参见NEP 41NEP 43

代码语言:javascript
复制
void *reserved2

用于可能的将来使用具有不同签名的循环选择器。

代码语言:javascript
复制
op_flags

重写每个 ufunc 操作数的默认操作数标志。

代码语言:javascript
复制
iter_flags

重写 ufunc 的默认 nditer 标志。

在 API 版本 0x0000000D 中添加

代码语言:javascript
复制
*core_dim_sizes

对于每个不同的核心尺寸,如果UFUNC_CORE_DIM_SIZE_INFERRED 等于 0,则是 p签名的可能大小

代码语言:javascript
复制
*core_dim_flags

每个不同的核心维度,一组标志(UFUNC_CORE_DIM_CAN_IGNOREUFUNC_CORE_DIM_SIZE_INFERRED

代码语言:javascript
复制
*identity_value

缩减的身份,当PyUFuncObject.identity 等于PyUFunc_IdentityValue时。

代码语言:javascript
复制
UFUNC_CORE_DIM_CAN_IGNORE

如果维度名称以 ? 结尾

代码语言:javascript
复制
UFUNC_CORE_DIM_SIZE_INFERRED

若维度大小将由操作数确定,并非来自 frozen 签名

PyArrayIter_Type 和 PyArrayIterObject
代码语言:javascript
复制
PyArrayIter_Type

这是一个迭代器对象,它可以轻松地循环访问 N 维数组。 这是从 ndarray 的 flat 属性返回的对象。 它还广泛用于整体实现内部,用于循环访问 N 维数组。 interface 已实现,使得可以对迭代器对象进行索引(使用 1-d 索引),并且一些方法通过tp_methods表进行了实现。 此对象实现了next方法,并且可以在 Python 中使用任何可以使用迭代器的地方。

代码语言:javascript
复制
type PyArrayIterObject

PyArrayIter_Type对象对应的 C-结构是PyArrayIterObject. PyArrayIterObject 用于跟踪指向 N 维数组的指针。 它包含相关信息,用于快速遍历数组。 指针可以通过三种基本方法进行调整:1) 以 C 风格连续的方式前进到数组中的“下一个”位置,2) 前进到数组中的任意 N 维坐标,和 3) 前进到数组中的任意一维索引。 这些计算中使用了PyArrayIterObject结构的成员。 迭代器对象保留其数组的维度和步幅信息。这可以根据需要进行“广播”,或者仅循环特定维度。

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  nd_m1;
  npy_intp  index;
  npy_intp  size;
  npy_intp  coordinates[NPY_MAXDIMS];
  npy_intp  dims_m1[NPY_MAXDIMS];
  npy_intp  strides[NPY_MAXDIMS];
  npy_intp  backstrides[NPY_MAXDIMS];
  npy_intp  factors[NPY_MAXDIMS];
  PyArrayObject  *ao;
  char  *dataptr;
  npy_bool  contiguous;
}  PyArrayIterObject; 
代码语言:javascript
复制
int nd_m1

(N-1) 其中 (N) 是底层数组中的维数。

代码语言:javascript
复制
index

当前数组的 1-d 索引。

代码语言:javascript
复制
size

底层数组的总大小。

代码语言:javascript
复制
*coordinates

一个 (N) -维数组的索引。

代码语言:javascript
复制
*dims_m1

每个维度中数组的大小减 1。

代码语言:javascript
复制
*strides

数组的步幅。在每个维度中,跳到下一个元素需要多少字节。

代码语言:javascript
复制
*backstrides

从维度末尾跳回到其开头需要多少字节。注意 backstrides[k] == strides[k] * dims_m1[k],但它存储在这里是一种优化。

代码语言:javascript
复制
*factors

此数组用于计算从 1-d 索引到 N-d 索引的所需乘积。

代码语言:javascript
复制
*ao

创建此迭代器表示的基础 ndarray 的指针。

代码语言:javascript
复制
char *dataptr

此成员指向由索引指示的 ndarray 中的元素。

代码语言:javascript
复制
contiguous

如果底层数组为NPY_ARRAY_C_CONTIGUOUS,则此标志为真。它用于尽可能简化计算。

如何在 C 级别上使用数组迭代器在后续部分中有更详细的解释。通常情况下,您无需关注迭代器对象的内部结构,而只需通过宏 PyArray_ITER_NEXT (it)、PyArray_ITER_GOTO (it, dest) 或 PyArray_ITER_GOTO1D (it, index) 与之交互即可。所有这些宏都要求参数 it 是一个 PyArrayIterObject*。

PyArrayMultiIter_TypePyArrayMultiIterObject
代码语言:javascript
复制
PyArrayMultiIter_Type

这种类型提供了一种封装了广播概念的迭代器。它允许将 (N) 个数组一起广播,以便循环按照 C 风格的连续方式在广播的数组上进行。相应的 C 结构是 PyArrayMultiIterObject,其内存布局必须从传递给 PyArray_Broadcast (obj) 函数的任何对象 obj 开始。通过调整数组迭代器来执行广播,使得每个迭代器表示广播的形状和大小,但其步幅被调整,以便在每次迭代中使用数组中的正确元素。

代码语言:javascript
复制
type PyArrayMultiIterObject
代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  numiter;
  npy_intp  size;
  npy_intp  index;
  int  nd;
  npy_intp  dimensions[NPY_MAXDIMS];
  PyArrayIterObject  *iters[NPY_MAXDIMS];
}  PyArrayMultiIterObject; 
代码语言:javascript
复制
int numiter

需要广播到相同形状的数组数量。

代码语言:javascript
复制
size

广播的总大小。

代码语言:javascript
复制
index

广播结果中当前的(1-d)索引。

代码语言:javascript
复制
int nd

广播结果中的维数数量。

代码语言:javascript
复制
*dimensions

广播结果的形状(仅使用 nd 个槽)。

代码语言:javascript
复制
**iters

一个包含为一起广播的数组调整过迭代器的迭代器对象数组。返回时,这些迭代器已调整好以进行广播。

PyArrayNeighborhoodIter_TypePyArrayNeighborhoodIterObject
代码语言:javascript
复制
PyArrayNeighborhoodIter_Type

这是一个迭代器对象,使得在 N 维邻域上循环变得��易。

代码语言:javascript
复制
type PyArrayNeighborhoodIterObject

与对象 PyArrayNeighborhoodIter_Type 对应的 C 结构是 PyArrayNeighborhoodIterObject

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  int  nd_m1;
  npy_intp  index,  size;
  npy_intp  coordinates[NPY_MAXDIMS]
  npy_intp  dims_m1[NPY_MAXDIMS];
  npy_intp  strides[NPY_MAXDIMS];
  npy_intp  backstrides[NPY_MAXDIMS];
  npy_intp  factors[NPY_MAXDIMS];
  PyArrayObject  *ao;
  char  *dataptr;
  npy_bool  contiguous;
  npy_intp  bounds[NPY_MAXDIMS][2];
  npy_intp  limits[NPY_MAXDIMS][2];
  npy_intp  limits_sizes[NPY_MAXDIMS];
  npy_iter_get_dataptr_t  translate;
  npy_intp  nd;
  npy_intp  dimensions[NPY_MAXDIMS];
  PyArrayIterObject*  _internal_iter;
  char*  constant;
  int  mode;
}  PyArrayNeighborhoodIterObject; 
PyArrayFlags_TypePyArrayFlagsObject
代码语言:javascript
复制
PyArrayFlags_Type

当从 Python 检索 flags 属性时,将构造这种特殊的内置对象。这种特殊类型通过将其作为属性访问这些不同的标志,或者通过将其作为字典访问,其中标志名称作为条目,使得更容易处理不同的标志。

代码语言:javascript
复制
type PyArrayFlagsObject
代码语言:javascript
复制
typedef  struct  PyArrayFlagsObject  {
  PyObject_HEAD
  PyObject  *arr;
  int  flags;
}  PyArrayFlagsObject; 
ScalarArrayTypes

对于数组中可能存在的不同内置数据类型,每个都有一个 Python 类型。其中大部分只是对应的 C 中数据类型的简单包装。这些类型的 C 名称为Py{TYPE}ArrType_Type,其中{TYPE}可以是

BoolByteShortIntLongLongLongUByteUShortUIntULongULongLongHalfFloatDoubleLongDoubleCFloatCDoubleCLongDoubleStringUnicodeVoid,和Object

这些类型名称是 C-API 的一部分,因此可以在扩展 C 代码中创建它们。还有一个PyIntpArrType_Type和一个PyUIntpArrType_Type,它们可以简单地替代可以在平台上保存指针的整数类型之一。这些标量对象的结构不暴露给 C 代码。函数PyArray_ScalarAsCtype(…)可用于从数组标量中提取 C 类型值,而函数PyArray_Scalar(…)可用于从 C 值构造数组标量。

其他 C 结构

发现在 NumPy 开发中几个新的 C 结构非常有用。这些 C 结构至少在一个 C-API 调用中被使用,因此在此进行了文档化。定义这些结构的主要原因是为了简化使用 Python ParseTuple C-API,将 Python 对象转换为有用的 C 对象。

PyArray_Dims
代码语言:javascript
复制
type PyArray_Dims

当需要解释形状和/或步幅信息时,此结构非常有用。该结构是:

代码语言:javascript
复制
typedef  struct  {
  npy_intp  *ptr;
  int  len;
}  PyArray_Dims; 

该结构的成员有

代码语言:javascript
复制
*ptr

指向(npy_intp)整数列表的指针,通常表示数组形状或数组步幅。

代码语言:javascript
复制
int len

整数列表的长度。假定可以安全地访问ptr[0]至ptr[len-1]。

PyArray_Chunk
代码语言:javascript
复制
type PyArray_Chunk

这相当于 Python 中缓冲区对象结构,直到 ptr 成员。在 32 位平台上(即如果NPY_SIZEOF_INT == NPY_SIZEOF_INTP),len 成员也与缓冲区对象的等效成员匹配。用于表示通用单段内存块。

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  PyObject  *base;
  void  *ptr;
  npy_intp  len;
  int  flags;
}  PyArray_Chunk; 

其成员有

代码语言:javascript
复制
*base

此内存块来自的 Python 对象。需要这样做以正确计算内存。

代码语言:javascript
复制
void *ptr

指向内存单段块的起始位置的指针。

代码语言:javascript
复制
len

段的长度(以字节为单位)。

代码语言:javascript
复制
int flags

任何应该用于解释内存的数据标志(例如NPY_ARRAY_WRITEABLE)。

PyArrayInterface

另请参阅

数组接口协议

代码语言:javascript
复制
type PyArrayInterface

PyArrayInterface 结构定义了 NumPy 和其他扩展模块可以使用的快速数组接口协议。支持快速数组接口协议的对象的 __array_struct__ 方法应返回一个包含指向 PyArrayInterface 结构的指针的 PyCapsule,其中包含数组的相关详细信息。创建新数组后,应DECREF该属性,这将释放 PyArrayInterface 结构的内存。记得INCREF获取 __array_struct__ 属性的对象,并将新 PyArrayObject 的 base 成员指向同一对象。通过这种方式,数组的内存将正确管理。

代码语言:javascript
复制
typedef  struct  {
  int  two;
  int  nd;
  char  typekind;
  int  itemsize;
  int  flags;
  npy_intp  *shape;
  npy_intp  *strides;
  void  *data;
  PyObject  *descr;
}  PyArrayInterface; 
代码语言:javascript
复制
int two

作为健全性检查的整数 2。

代码语言:javascript
复制
int nd

数组中的维度数。

代码语言:javascript
复制
char typekind

根据类型字符串约定指示存在什么类型的数组的字符,将 ‘t’ -> 位域,‘b’ -> 布尔值,‘i’ -> 有符号整数,‘u’ -> 无符号整数,‘f’ -> 浮点,‘c’ -> 复数浮点,‘O’ -> 对象,‘S’ -> (字节)字符串,‘U’ -> Unicode,‘V’ -> void。

代码语言:javascript
复制
int itemsize

数组中每个项所需的字节数。

代码语言:javascript
复制
int flags

任何一个位 NPY_ARRAY_C_CONTIGUOUS (1),NPY_ARRAY_F_CONTIGUOUS (2),NPY_ARRAY_ALIGNED (0x100),NPY_ARRAY_NOTSWAPPED (0x200),或 NPY_ARRAY_WRITEABLE (0x400),以指示有关数据的一些信息。实际上,可以从其他参数确定标志 NPY_ARRAY_ALIGNEDNPY_ARRAY_C_CONTIGUOUSNPY_ARRAY_F_CONTIGUOUS。标志 NPY_ARR_HAS_DESCR (0x800) 也可以设置,以向消费版本 3 数组接口的对象指示结构的 descr 成员存在(版本 2 的数组接口将忽略它)。

代码语言:javascript
复制
*shape

包含数组每个维度的大小的数组。

代码语言:javascript
复制
*strides

包含在每个维度中跳过下一个元素所需的字节数的数组。

代码语言:javascript
复制
void *data

指向数组第一个元素的指针。

代码语言:javascript
复制
*descr

描述数据类型详细信息的 Python 对象(与__array_interface__中的descr键相同)。如果typekinditemsize提供足够的信息,这个字段可以为NULL。除非在flags中打开了NPY_ARR_HAS_DESCR标志,否则此字段也会被忽略。

内部使用的结构

内部,该代码使用了一些额外的 Python 对象,主要用于内存管理。这些类型无法直接从 Python 访问,并且不会暴露给 C-API。它们在此处仅用于完整性和帮助理解代码。

代码语言:javascript
复制
type PyUFunc_Loop1d

简单的 C 结构链表,包含了为用户定义的数据类型的每个定义的签名定义 1-d 循环所需的信息。

代码语言:javascript
复制
PyArrayMapIter_Type

使用此 Python 类型处理高级索引。它只是一个松散的包装器,包装了包含高级数组索引所需变量的 C 结构。

代码语言:javascript
复制
type PyArrayMapIterObject

PyArrayMapIter_Type相关联的 C 结构。如果你正在尝试理解高级索引映射代码,这个结构很有用。它在arrayobject.h头文件中定义。此类型未暴露给 Python,可以用 C 结构替换。作为 Python 类型,它利用引用计数内存管理。

PyArray_Dims
代码语言:javascript
复制
type PyArray_Dims

当形状和/或步长信息需要被解释时,这个结构非常有用。结构是:

代码语言:javascript
复制
typedef  struct  {
  npy_intp  *ptr;
  int  len;
}  PyArray_Dims; 

这个结构的成员是

代码语言:javascript
复制
*ptr

指向一个(npy_intp)整数列表的指针,通常表示数组的形状或数组的步长。

代码语言:javascript
复制
int len

整数列表的长度。假定可以安全访问ptr[0]到ptr[len-1]。

PyArray_Chunk
代码语言:javascript
复制
type PyArray_Chunk

这与 Python 中的缓冲对象结构相当,直到 ptr 成员。在 32 位平台上( if NPY_SIZEOF_INT == NPY_SIZEOF_INTP),len 成员也与缓冲对象的等效成员匹配。它用于表示通用单段内存块。

代码语言:javascript
复制
typedef  struct  {
  PyObject_HEAD
  PyObject  *base;
  void  *ptr;
  npy_intp  len;
  int  flags;
}  PyArray_Chunk; 

这些成员是

代码语言:javascript
复制
*base

分配这块内存的 Python 对象。需要这样以便能够正确计算内存使用。

代码语言:javascript
复制
void *ptr

指向单个内存块的起始指针。

代码语言:javascript
复制
len

段的字节长度。

代码语言:javascript
复制
int flags

用于解释内存的任何数据标志(例如 NPY_ARRAY_WRITEABLE)。

PyArrayInterface

另请参见

数组接口协议

代码语言:javascript
复制
type PyArrayInterface

PyArrayInterface结构被定义为 NumPy 和其他扩展模块可以使用快速数组接口协议。支持快速数组接口协议的对象的__array_struct__方法应返回包含指向具有数组的相关细节的PyArrayInterface结构的指针的PyCapsule。创建新数组后,应DECREF该属性,这将释放PyArrayInterface结构。记得INCREF这个对象(其__array_struct__属性已被检索)并将新PyArrayObject的 base 成员指向同一对象。这样数组的内存将得到正确管理。

代码语言:javascript
复制
typedef  struct  {
  int  two;
  int  nd;
  char  typekind;
  int  itemsize;
  int  flags;
  npy_intp  *shape;
  npy_intp  *strides;
  void  *data;
  PyObject  *descr;
}  PyArrayInterface; 
代码语言:javascript
复制
int two

整数2作为健全性检查。

代码语言:javascript
复制
int nd

数组中的维度数。

代码语言:javascript
复制
char typekind

根据类型字符串约定指示出现的数组类型的字符,‘t’ -> 位字段,‘b’ -> 布尔,‘i’ -> 有符号整数,‘u’ -> 无符号整数,‘f’ -> 浮点数,‘c’ -> 复数浮点数,‘O’ -> 对象,‘S’ -> (字节)字符串,‘U’ -> Unicode,‘V’ -> 空。

代码语言:javascript
复制
int itemsize

数组中每个项所需的字节数。

代码语言:javascript
复制
int flags

位之一NPY_ARRAY_C_CONTIGUOUS(1)、NPY_ARRAY_F_CONTIGUOUS(2)、NPY_ARRAY_ALIGNED(0x100)、NPY_ARRAY_NOTSWAPPED(0x200)或NPY_ARRAY_WRITEABLE(0x400)用于指示数据的某些内容。NPY_ARRAY_ALIGNEDNPY_ARRAY_C_CONTIGUOUSNPY_ARRAY_F_CONTIGUOUS标志实际上可以从其他参数中确定。标志NPY_ARR_HAS_DESCR(0x800)也可以设置为指示消耗版本 3 数组接口的对象,结构的 descr 成员存在(对于消耗版本 2 的数组接口的对象将被忽略)。

代码语言:javascript
复制
*shape

包含每个维度中数组大小的数组。

代码语言:javascript
复制
*strides

包含跳转到每个维度中下一个元素所需字节数的数组。

代码语言:javascript
复制
void *data

指向数组第一个元素的指针。

代码语言:javascript
复制
*descr

描述数据类型的 Python 对象更详细(与__array_interface__中的descr键相同)。如果typekinditemsize提供足够信息,则此字段可以是NULL。除非flags中打开了NPY_ARR_HAS_DESCR标志,否则此字段也会被忽略。

内部使用的结构

在内部,代码主要用于内存管理的一些额外的 Python 对象。这些类型不能直接从 Python 访问,也未暴露给 C-API。它们仅在此列出,以完整和帮助理解代码。

代码语言:javascript
复制
type PyUFunc_Loop1d

包含定义用户定义数据类型的每个签名的 1-d 循环所需信息的 C 结构的简单链接列表。

代码语言:javascript
复制
PyArrayMapIter_Type

高级索引使用这种 Python 类型处理。它只是围绕包含高级数组索引所需变量的 C 结构的松散包装。

代码语言:javascript
复制
type PyArrayMapIterObject

PyArrayMapIter_Type相关联的 C 结构。如果您试图理解高级索引映射代码,这个结构非常有用。它在arrayobject.h头文件中定义。这种类型并未暴露给 Python,可以用 C 结构替代。作为 Python 类型,它利用引用计数的内存管理。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • numpy.distutils.misc_util
  • numpy.distutils.ccompiler
  • numpy.distutils.ccompiler_opt
  • numpy.distutils.cpuinfo.cpu
  • numpy.distutils.core.Extension
  • numpy.distutils.exec_command
  • numpy.distutils.log.set_verbosity
  • numpy.distutils.system_info.get_info
  • numpy.distutils.system_info.get_standard_file
  • NumPy distutils - 用户指南
    • SciPy 结构
      • SciPy 包的要求
        • setup.py 文件
          • SciPy 纯 Python 包示例
          • Configuration实例属性
          • Configuration实例方法
          • 使用模板转换.src文件
          • 其他文件
          • numpy.distutils.misc_util中的有用函数
          • numpy.distutils.system_info 模块
          • numpy.distutils.cpuinfo 模块
          • numpy.distutils.log 模块
          • numpy.distutils.exec_command 模块
        • __init__.py 文件
          • NumPy Distutils 中的额外功能
            • 在 setup.py 脚本中为库指定 config_fc 选项
            • 从源代码中获取额外的 Fortran 77 编译器选项
          • SciPy 结构
            • SciPy 包的要求
              • setup.py文件
                • SciPy 纯 Python 包示例
                • Configuration实例属性
                • Configuration实例方法
                • 使用模板转换.src文件
                • 其他文件
                • numpy.distutils.misc_util中的实用函数
                • numpy.distutils.system_info模块
                • numpy.distutils.cpuinfo模块
                • numpy.distutils.log模块
                • numpy.distutils.exec_command模块
                • SciPy 纯 Python 软件包示例
                • Configuration实例的属性
                • Configuration实例的方法
                • 使用模板转换.src文件
                • Fortran 文件
                • 其他文件
                • numpy.distutils.misc_util中的有用函数
                • numpy.distutils.system_info模块
                • numpy.distutils.cpuinfo模块
                • numpy.distutils.log模块
                • numpy.distutils.exec_command模块
              • __init__.py文件
                • NumPy Distutils 的额外功能
                  • 在 setup.py 脚本中为库指定 config_fc 选项
                  • 从源代码获取额外的 Fortran 77 编译器选项
                  • 在 setup.py 脚本中为库指定 config_fc 选项。
                  • 从源码中获取额外的 Fortran 77 编译器选项。
              • numpy.distutils 的状态和迁移建议
                • 迁移建议
                  • 迁移到 Meson
                  • 迁移到 CMake / scikit-build
                  • 迁移到 setuptools
                • 迁移建议
                  • 迁移至 Meson
                  • 迁移到 CMake / scikit-build
                  • 迁移到setuptools
                  • 转移到 Meson。
                  • 转移到 CMake / scikit-build。
                  • 转移到setuptools
                • numpy.distutils与setuptools的交互
                • NumPy C-API
                • Python 类型和 C 结构
                  • 定义了新的 Python 类型
                    • PyArray_Type 和 PyArrayObject
                    • PyArrayDescr_Type 和 PyArray_Descr
                    • PyUFunc_Type 和 PyUFuncObject
                    • PyArrayIter_Type 和 PyArrayIterObject
                    • PyArrayMultiIter_Type 和 PyArrayMultiIterObject
                    • PyArrayNeighborhoodIter_Type 和 PyArrayNeighborhoodIterObject
                    • PyArrayFlags_Type 和 PyArrayFlagsObject
                    • ScalarArrayTypes
                  • 其他 C-结构
                    • PyArray_Dims
                    • PyArray_Chunk
                    • PyArrayInterface
                    • 内部使用的结构
                  • 定义的新 Python 类型
                    • PyArray_Type和PyArrayObject
                    • PyArrayDescr_Type 和 PyArray_Descr
                    • PyArrayIter_Type 和 PyArrayIterObject
                    • PyArrayMultiIter_Type 和 PyArrayMultiIterObject
                    • PyArrayNeighborhoodIter_Type 和 PyArrayNeighborhoodIterObject
                    • PyArrayFlags_Type 和 PyArrayFlagsObject
                    • 标量数组类型
                    • - PyArray_Type 和 PyArrayObject
                    • PyArrayDescr_Type 和 PyArray_Descr
                    • PyUFunc_Type 和 PyUFuncObject
                    • PyArrayIter_Type 和 PyArrayIterObject
                    • PyArrayMultiIter_Type 和 PyArrayMultiIterObject
                    • PyArrayNeighborhoodIter_Type 和 PyArrayNeighborhoodIterObject
                    • PyArrayFlags_Type 和 PyArrayFlagsObject
                    • ScalarArrayTypes
                  • 其他 C 结构
                    • PyArray_Dims
                    • PyArray_Chunk
                    • PyArrayInterface
                    • 内部使用的结构
                    • PyArray_Dims
                    • PyArray_Chunk
                    • PyArrayInterface
                    • 内部使用的结构
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档