当前位置: 首页 > news >正文

NumPy 2.x 完全指南【十一】N 维数组对象(ndarray)

文章目录

  • 1. 概述
  • 2. 构造函数
  • 3. 索引
  • 4. 内存布局
  • 5. 数组属性
    • 5.1 内存布局属性
    • 5.2 数据类型
    • 5.3 数组接口
    • 5.4 `ctypes` 接口
    • 5.5 其他属性
  • 6. 数组方法
    • 6.1 数组转换
    • 6.2 形状操作
    • 6.3 元素选择与操作
    • 6.4 计算相关
  • 7. 算术运算、矩阵乘法与比较操作
    • 7.1 比较运算符
    • 7.2 真值测试
    • 7.3 单目运算符
    • 7.4 算术运算符
    • 7.5 复合赋值运算
    • 7.6 矩阵乘法
  • 8. 特殊方法
    • 8.1 标准库函数支持
    • 8.2 基本定制方法
    • 8.3 容器协议实现
    • 8.4 类型转换方法
    • 8.5 字符串表示
    • 8.6 类型工具方法

1. 概述

NumPy 中有三个描述数组数据的基本对象:

  • ndarrayN 维数组):存储多维数据,描述数据在内存中的布局,提供对数据的批量操作接口,如数学运算、索引、广播等。
  • dtype(数据类型对象):定义单个元素的内存布局和解释方式,支持基本类型、复合类型(结构化数组)和自定义类型。
  • Array Scalar(数组标量):通过索引访问单个数组元素时,返回一个与 dtype 对应的标量对象,提供与 Python 原生类型兼容的接口,同时保留 NumPy 类型特性。

它们之间的关系示意图:
在这里插入图片描述

图示内容解析:

  • ndarray 本身,包含元数据(Header)和数据缓冲区两部分。
  • 数组中元素的类型由一个单独的数据类型对象(dtype)指定,每个 ndarray 都与一个数据类型对象相关联。
  • 当访问数组中的单个元素时返回的数组标量 Python 对象。

在之前的篇章中,有提到 ndarrayNumPy 中最重要的一个类,它表示 N 维数组对象,该对象是用于存放同类型元素的多维数组。接下来我们全面的了解一下 ndarray ,在官方文档中主要提及了以下知识点:

  • 构造函数
  • 索引
  • 内存布局
  • 数组属性
  • 数组方法
  • 算术运算、矩阵乘法和比较操作
  • 特殊方法

2. 构造函数

ndarray 提供了一个底层的构造函数,适用于从现有缓冲区(如二进制数据)创建数组或高级优化场景。

函数定义:

np.ndarray(shape, dtype=float, buffer=None, offset=0, strides=None, order='C')

参数说明:

  • shape:数组维度。
  • dtype:元素类型。
  • buffer:从现有内存缓冲区(如 bytesbytearray)创建数组。
  • offset:缓冲区中的起始字节偏移量(默认为 0 )。
  • strides:自定义内存步长。
  • order:内存布局顺序。

简单示例:

# 原始数据
data = np.arange(6, dtype=np.int32).tobytes()  #  [0,1,2,3,4,5]# 创建一个 2x3 数组,但每行间隔 8 字节(默认每行间隔 12 字节)
arr = np.ndarray(shape=(2, 3), dtype=np.int32, buffer=data, strides=(8, 4))print(arr)
# 输出:
# [[0 1 2]
#  [2 3 4]]

⚠️ 提示: 大多数场景下,都是通过高层简洁的接口创建数组。

3. 索引

NumPy 根据索引对象的类型划分了三种索引方式:

  • 基础索引:只使用索引序号或切片。
  • 高级索引:使用整数数组或布尔数组。
  • 字段访问:通过字段名访问(结构化数组)。

⚠️ 提示: 之前已经介绍过了基础索引,后续会单独介绍其他的。

4. 内存布局

无论数组维度多高,数据最终存储在连续的一维内存块中,通过索引规则将 N 维坐标转换为内存中的偏移量。

涉及到的关键属性有:

  • shape:数组形状。
  • strides:每个维度上移动一个元素所需的字节数。
  • dtype:元素类型。

⚠️ 提示: 后续单独介绍内存布局。

5. 数组属性

数组属性是数组的核心组成部分,反映了数组本身的内在信息,NumPy 数组对象(ndarray)属性分为以下几类:

  • 内存布局
  • 数据类型
  • 其他属性
  • 数组接口协议
  • ctypes 外部函数接口

5.1 内存布局属性

属性名类型描述
ndarray.flags属性数组内存布局的信息(如连续性、读写权限等)
ndarray.shape属性数组维度组成的元组(例如 (3, 4) 表示 3 行 4 列的二维数组)
ndarray.strides属性遍历数组时,每个维度中步进的字节数组成的元组
ndarray.ndim属性数组的维度数量(如标量=0,向量=1,矩阵=2)
ndarray.data属性指向数组数据起始位置的 Python 缓冲区对象
ndarray.size属性数组中元素的总数(等于各维度大小的乘积)
ndarray.itemsize属性单个数组元素的字节长度(如 float64 类型的元素为 8 字节)
ndarray.nbytes属性数组元素消耗的总字节数(等于 size * itemsize
ndarray.base属性若数组共享其他对象的内存,则指向基对象;否则为 None

5.2 数据类型

属性名类型描述
ndarray.dtype属性数组元素的数据类型(如 int32, float64, 或自定义类型)

5.3 数组接口

属性名/方法名类型描述
__array_interface__属性数组接口的 Python 端实现(提供元数据字典)
__array_struct__属性数组接口的 C 端实现(用于与 C 扩展交互)

5.4 ctypes 接口

属性名类型描述
ndarray.ctypes属性简化数组与 ctypes 模块交互的对象(提供指针、形状等底层访问)

5.5 其他属性

属性名类型描述
ndarray.T属性转置数组的视图(等价于 np.transpose()
ndarray.real属性数组的实部(对复数数组有效)
ndarray.imag属性数组的虚部(对复数数组有效)
ndarray.flat属性数组的一维迭代器(可遍历所有元素)

⚠️ 提示: 之前已经介绍过常用的数组属性,没有介绍到的会后续涉及到的章节进行详细介绍。

6. 数组方法

数组对象(ndarray)包含多种操作方法,通常返回数组结果。按功能进行分类的方法有:

  • 数组转换方法
  • 形状操作
  • 元素选择与操作
  • 计算相关

6.1 数组转换

方法名类型描述
ndarray.item(*args)方法将数组的一个元素复制为标准 Python 标量并返回
ndarray.tolist()方法将数组转换为 a.ndim 层深度的嵌套 Python 列表
ndarray.tostring([order])方法tobytes 的兼容性别名,行为完全相同
ndarray.tobytes([order])方法生成包含数组原始数据字节的 Python bytes 对象
ndarray.tofile(fid[, sep, format])方法将数组以文本或二进制(默认)形式写入文件
ndarray.dump(file)方法将数组的 pickle 序列化保存到指定文件
ndarray.dumps()方法返回数组的 pickle 序列化字符串
ndarray.astype(dtype[, ...])方法创建转换到指定数据类型的数组副本
ndarray.byteswap([inplace])方法交换数组元素的字节顺序(大小端转换)
ndarray.copy([order])方法返回数组的深拷贝
ndarray.view([dtype][, type])方法创建共享数据的新视图(可指定数据类型)
ndarray.getfield(dtype[, offset])方法以特定类型返回数组的字段(内存布局操作)
ndarray.setflags([write, align, uic])方法设置数组标志(可写性、内存对齐等)
ndarray.fill(value)方法用标量值填充整个数组

6.2 形状操作

方法名类型描述
ndarray.reshape(shape[, ...])方法返回新形状的数组(数据不变)
ndarray.resize(new_shape[, refcheck])方法原地修改数组形状和大小
ndarray.transpose(*axes)方法返回轴转置后的数组视图
ndarray.swapaxes(axis1, axis2)方法交换两个轴的数组视图
ndarray.flatten([order])方法返回展平为一维的数组副本
ndarray.ravel([order])方法返回展平为一维的数组视图
ndarray.squeeze([axis])方法移除长度为 1 的轴

6.3 元素选择与操作

方法名类型描述
ndarray.take(indices[, axis, ...])方法从指定索引处提取元素构建新数组
ndarray.put(indices, values[, mode])方法将值按索引写入数组的扁平化视图
ndarray.repeat(repeats[, axis])方法重复数组元素生成新数组
ndarray.choose(choices[, ...])方法用索引数组从多个选择中构造新数组
ndarray.sort([axis, kind, order])方法原地排序数组
ndarray.argsort([axis, ...])方法返回排序后的元素索引
ndarray.partition(kth[, ...])方法部分排序数组(使第 k 个元素处于有序位置)
ndarray.argpartition(kth[, ...])方法返回部分排序的索引
ndarray.searchsorted(v[, ...])方法查找元素应插入的位置以保持有序
ndarray.nonzero()方法返回非零元素的索引
ndarray.compress(condition[, ...])方法按条件沿轴选择切片
ndarray.diagonal([offset, ...])方法返回指定对角线元素

6.4 计算相关

方法名类型描述
ndarray.max([axis, out, ...])方法沿轴返回最大值
ndarray.argmax([axis, out, ...])方法返回最大值索引
ndarray.min([axis, out, ...])方法沿轴返回最小值
ndarray.argmin([axis, out, ...])方法返回最小值索引
ndarray.clip([min, max, out])方法限制数组值在 [min, max] 范围内
ndarray.conj()方法返回所有元素的复共轭
ndarray.round([decimals, out])方法返回四舍五入到指定小数位的数组
ndarray.trace([offset, ...])方法沿对角线求和
ndarray.sum([axis, ...])方法沿轴求和(支持指定数据类型防止溢出)
ndarray.cumsum([axis, ...])方法沿轴返回累计和
ndarray.mean([axis, ...])方法沿轴计算平均值
ndarray.var([axis, ...])方法沿轴计算方差
ndarray.std([axis, ...])方法沿轴计算标准差
ndarray.prod([axis, ...])方法沿轴计算乘积
ndarray.cumprod([axis, ...])方法沿轴返回累计乘积
ndarray.all([axis, ...])方法检查是否所有元素为 True
ndarray.any([axis, ...])方法检查是否有任意元素为 True

7. 算术运算、矩阵乘法与比较操作

基础规则:

  • 逐元素操作:所有算术和比较运算均为逐元素操作,返回新的 ndarray 对象。
  • 通用函数等价:每个操作均等价于对应的 NumPy 通用函数(ufunc)。

7.1 比较运算符

运算符(方法名)等价表达式描述
ndarray.__lt__(value)self < value逐元素小于比较
ndarray.__le__(value)self <= value逐元素小于等于比较
ndarray.__gt__(value)self > value逐元素大于比较
ndarray.__ge__(value)self >= value逐元素大于等于比较
ndarray.__eq__(value)self == value逐元素等于比较
ndarray.__ne__(value)self != value逐元素不等于比较

7.2 真值测试

方法名描述
ndarray.__bool__()当数组仅含 1 个元素时返回 True,否则抛出 ValueError

注意事项

  • 数组的真值测试会调用 ndarray.__bool__,如果数组中的元素数量不为 1,会引发错误,因为此类数组的真值是模糊的。在这种情况下,请使用 .any().all() 来明确表达您的意图。(如果您想检查数组是否为空,可以使用例如 .size > 0。)

7.3 单目运算符

运算符方法类型描述
ndarray.__neg__()方法逐元素取负:-self
ndarray.__pos__()方法逐元素取正:+self
ndarray.__abs__()方法逐元素取绝对值
ndarray.__invert__()方法逐元素按位取反:~self

7.4 算术运算符

运算符方法类型描述
ndarray.__add__(value)方法逐元素加法:self + value
ndarray.__sub__(value)方法逐元素减法:self - value
ndarray.__mul__(value)方法逐元素乘法:self * value
ndarray.__truediv__(value)方法逐元素真除法:self / value
ndarray.__floordiv__(value)方法逐元素地板除法:self // value
ndarray.__mod__(value)方法逐元素取模:self % value
ndarray.__divmod__(value)方法返回 (商, 余数) 元组
ndarray.__pow__(value[, mod])方法逐元素幂运算(忽略第三个参数)
ndarray.__lshift__(value)方法逐元素左移位:self << value
ndarray.__rshift__(value)方法逐元素右移位:self >> value
ndarray.__and__(value)方法逐元素按位与:self & value
ndarray.__or__(value)方法逐元素按位或:self | value
ndarray.__xor__(value)方法逐元素按位异或:self ^ value

注意事项

  • pow 的第三个参数会被忽略(底层 ufunc 仅接受两个参数)。
  • 不支持反向运算符(如 __radd__),需通过 __array_ufunc__ 自定义行为。

7.5 复合赋值运算

运算符方法类型描述
ndarray.__iadd__(value)方法原地加法:self += value
ndarray.__isub__(value)方法原地减法:self -= value
ndarray.__imul__(value)方法原地乘法:self *= value
ndarray.__itruediv__(value)方法原地真除法:self /= value
ndarray.__ifloordiv__(value)方法原地地板除法:self //= value
ndarray.__imod__(value)方法原地取模:self %= value
ndarray.__ipow__(value)方法原地幂运算:self ​**​= value
ndarray.__ilshift__(value)方法原地左移位:self <<= value
ndarray.__irshift__(value)方法原地右移位:self >>= value
ndarray.__iand__(value)方法原地按位与:self &= value
ndarray.__ior__(value)方法原地按位或:self |= value
ndarray.__ixor__(value)方法原地按位异或:self ^= value

7.6 矩阵乘法

运算符方法类型描述
ndarray.matmul(value)方法矩阵乘法:self @ value

8. 特殊方法

8.1 标准库函数支持

方法名类型描述
ndarray.__copy__()方法实现 copy.copy() 的浅拷贝逻辑
ndarray.__deepcopy__(memo)方法实现 copy.deepcopy() 的深拷贝逻辑
ndarray.__reduce__()方法序列化数组(pickling 支持)
ndarray.__setstate__(state)方法反序列化数组(unpickling 支持)

8.2 基本定制方法

方法名类型描述
ndarray.__new__(*args, ​**kwargs)方法构造新数组的工厂方法
ndarray.__array__([dtype])方法返回自身引用(当 dtype 匹配时)或副本
ndarray.__array_wrap__(array)方法返回与自身类型相同的数组视图

8.3 容器协议实现

方法名类型描述
ndarray.__len__()方法返回数组长度(第一维大小)
ndarray.__getitem__(key)方法实现索引操作 self[key]
ndarray.__setitem__(key, value)方法实现赋值操作 self[key] = value
ndarray.__contains__(key)方法实现成员检测 key in self

8.4 类型转换方法

方法名类型描述
ndarray.__int__()方法转换为整型(仅单元素数组有效)
ndarray.__float__()方法转换为浮点型(仅单元素数组有效)
ndarray.__complex__()方法转换为复数型(仅单元素数组有效)

8.5 字符串表示

方法名类型描述
ndarray.__str__()方法返回用户友好字符串表示(如 print(arr)
ndarray.__repr__()方法返回开发者调试用字符串表示

8.6 类型工具方法

方法名类型描述
ndarray.__class_getitem__(item)方法创建参数化类型包装器(用于类型注解)

相关文章:

  • 庐山派 HDMI Python 图像开发 K230图像传输方案
  • 在资源受限环境下,移动端如何实现流畅动画?如何在内存、CPU、GPU、网络等多种限制条件下,依然保持动画高帧率、低延迟、不卡顿?
  • 自定义协议与序列化
  • 大型商用货运无人机强势入局2025深圳eVTOL展
  • 【硬核数学】2. AI如何“学习”?微积分揭秘模型优化的奥秘《从零构建机器学习、深度学习到LLM的数学认知》
  • 亚远景-ASPICE与ISO 21434在汽车电子系统开发中的应用案例
  • 微服务项目->在线oj系统(Java版 - 5)
  • 机器学习第十六讲:K-means → 自动把超市顾客分成不同消费群体
  • Java—— File详解
  • VTK|箱体切割器
  • 【git进阶】git rebase(变基)
  • 前端子项目打包集成主项目实战指南
  • SOC-ESP32S3部分:1、ESP32开发IDF-5.4环境搭建
  • RV1126多线程获取SMARTP的GOP模式数据和普通GOP模式数据
  • 第二届parloo杯的RSA_Quartic_Quandary
  • 系统架构设计师考前冲刺笔记-第3章-软件架构设计
  • Pod 节点数量
  • 【Redis】快速列表结构
  • 没有公网ip怎么端口映射外网访问?使用内网穿透可以解决
  • upload-labs通关笔记-第12关 文件上传之白名单GET法
  • 讲述“外国货币上的中国故事”,《世界钱币上的中国印记》主题书刊出版发布
  • 澎湃思想周报|《混沌少年时》与青少年社媒禁令;自雇陷阱
  • 香港今年新股集资额已超600亿港元,暂居全球首位
  • 倒票“黄牛”屡禁不绝怎么破?业内:强化文旅市场票务公开制度
  • 80后女博士黄双燕拟提名为内蒙古盟市政府(行署)副职人选
  • 消息人士称俄方反对美国代表参加俄乌直接会谈