什么是 np.ndarray?
np.ndarray (N-dimensional Array) 是 NumPy 库定义的一个多维数组对象,你可以把它理解为一个表格,它可以是一维的(像列表)、二维的(像矩阵),甚至是三维、四维或更高维度的。

与 Python 内置的 list (列表) 相比,np.ndarray 具有以下核心优势,这也是 NumPy 库如此强大的原因:
- 性能优越:
np.ndarray中的所有元素必须是相同类型的数据(通常是数值类型),并且它们在内存中是连续存储的,这使得 NumPy 能够利用 CPU 的向量化指令进行高效计算,速度远快于 Python 的list。 - 丰富的函数库:NumPy 提供了大量的数学函数、线性代数函数、傅里叶变换函数等,可以直接对整个数组进行操作,无需编写循环,这极大地简化了代码并提高了效率。
- 广播机制:这是一个非常强大的特性,允许在不同形状的数组之间执行算术运算,NumPy 会自动将较小的数组“扩展”以匹配较大数组的形状,使得代码更简洁、高效。
- 便捷的索引和切片:
np.ndarray提供了比 Pythonlist更强大、更灵活的索引和切片功能,可以轻松访问和修改数组的任意部分。
如何创建 np.ndarray
创建 np.ndarray 的方法有很多,这里介绍最常用的几种:
1 从 Python 列表创建
这是最直接的方式,你可以从一维列表、二维列表等创建数组。
import numpy as np
# 从一维列表创建
arr1d = np.array([1, 2, 3, 4, 5])
print("一维数组:")
print(arr1d)
print("类型:", type(arr1d))
print("数据类型:", arr1d.dtype) # 默认会推断数据类型
# 从二维列表创建(类似矩阵)
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
print("\n二维数组:")
print(arr2d)
print("形状:", arr2d.shape) # (2, 3) 表示2行3列
2 使用 NumPy 内置函数创建
NumPy 提供了专门用于创建特定类型数组的函数,非常方便。

# 创建一个全为0的数组
zeros_arr = np.zeros((3, 4)) # 形状为3行4列
print("全0数组:")
print(zeros_arr)
# 创建一个全为1的数组
ones_arr = np.ones((2, 2), dtype=int) # 可以指定数据类型
print("\n全1数组:")
print(ones_arr)
# 创建一个单位矩阵
identity_matrix = np.eye(3)
print("\n单位矩阵:")
print(identity_matrix)
# 创建一个有固定范围的数组
range_arr = np.arange(10) # 类似 range(10)
print("\narange数组:")
print(range_arr)
# 创建一个有固定间隔的数组
linspace_arr = np.linspace(0, 1, 5) # 从0到1,生成5个等间距的点
print("\nlinspace数组:")
print(linspace_arr)
# 创建一个随机数组
random_arr = np.random.rand(3, 3) # 生成一个3x3的[0, 1)区间的随机浮点数数组
print("\n随机数组:")
print(random_arr)
np.ndarray 的核心属性
了解这些属性是操作数组的基础:
ndarray.shape:一个元组,表示数组的维度大小。(2, 3)表示一个2行3列的二维数组。ndarray.ndim:整数,表示数组的轴(维度)的数量,一维数组的ndim是 1,二维数组的ndim是 2。ndarray.size:整数,表示数组中元素的总数量,等于shape中所有元素的乘积。ndarray.dtype:描述数组元素类型的对象。int32,float64,bool等。ndarray.itemsize:数组中每个元素所占用的字节数。
arr = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float64)
print("数组:\n", arr)
print("形状:", arr.shape) # 输出: (2, 3)
print("维度:", arr.ndim) # 输出: 2
print("元素总数:", arr.size) # 输出: 6
print("数据类型:", arr.dtype) # 输出: float64
print("每个元素字节数:", arr.itemsize) # 输出: 8 (因为float64占8个字节)
np.ndarray 的核心操作
1 索引和切片
NumPy 的索引和切片语法与 Python 列表非常相似,但功能更强大。
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
# 获取单个元素
print("第一行第二列的元素:", arr[0, 1]) # 输出: 2
# 切片
print("\n第一行:")
print(arr[0, :]) # 或 arr[0]
print("\n第二列:")
print(arr[:, 1])
print("\n获取一个子矩阵 (前两行,后两列):")
print(arr[:2, 2:])
2 整数数组索引
使用一个列表或数组作为索引来选取特定的元素。
arr = np.array([[1, 2], [3, 4], [5, 6]])
print("原始数组:\n", arr)
# 选取第0行和第2行,第1列的元素
# 索引数组 [0, 2] 对应行,索引数组 [1] 对应列
print("\n使用整数数组索引选取的元素:", arr[[0, 2], [1]]) # 输出: [2 6]
3 布尔索引
使用一个布尔数组来筛选元素,非常直观。

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
# 创建一个布尔条件
condition = arr > 4
print("布尔条件:", condition) # 输出: [False False False False True True True True]
# 使用这个布尔数组进行索引
print("\n大于4的元素:", arr[condition]) # 输出: [5 6 7 8]
# 可以直接在索引中写表达式
print("\n小于等于4的元素:", arr[arr <= 4]) # 输出: [1 2 3 4]
4 数学运算
这是 NumPy 最强大的地方,对数组的运算会作用于每个元素,无需编写循环。
a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
# 加法
print("a + b:", a + b) # 输出: [11 22 33 44]
# 减法
print("a - b:", a - b) # 输出: [-9 -18 -27 -36]
# 乘法 (元素级)
print("a * b:", a * b) # 输出: [ 10 40 90 160]
# 除法
print("a / b:", a / b) # 输出: [0.1 0.1 0.1 0.1]
# 与标量的运算
print("a * 2:", a * 2) # 输出: [ 2 4 6 8]
# 平方
print("a ** 2:", a ** 2) # 输出: [ 1 4 9 16]
# 三角函数
print("sin(a):", np.sin(a)) # 输出: [ 0.84147098 0.90929743 0.14112001 -0.7568025 ]
5 广播
当两个形状不同的数组进行运算时,NumPy 会尝试通过“广播”机制使它们兼容。
广播规则:
- 如果两个数组的维度数不同,在较小的数组前面补
1。 - 如果两个数组在某个维度上的大小不同,其中一个必须是
1。 - 如果两个数组在任何维度上的大小都不匹配,且没有一个是
1,则会引发错误。
示例:
将一个一维数组 v 加到二维数组 m 的每一行上。
m = np.array([[1, 2, 3], [4, 5, 6]])
v = np.array([10, 20, 30])
# m 的形状是 (2, 3)
# v 的形状是 (3,)
# 广播过程:
# 1. v 的形状被扩展为 (1, 3) 来匹配 m 的维度数
# 2. v 的形状 (1, 3) 被扩展为 (2, 3) 以匹配 m 的形状
# NumPy 会将 v 的行复制一份
# 最终效果相当于:
# m + [[10, 20, 30],
# [10, 20, 30]]
result = m + v
print("m:\n", m)
print("v:\n", v)
print("m + v (广播后):\n", result)
# 输出:
# [[11 22 33]
# [14 25 36]]
修改 np.ndarray 的形状
ndarray.reshape(new_shape):返回一个具有新形状的数组,不修改原始数据,原始数组和返回的数组共享数据。ndarray.resize(new_shape):直接在原始数组上进行修改,改变其形状。ndarray.flatten():将多维数组展平为一维数组,并返回一个副本。
arr = np.arange(6)
print("原始数组:", arr) # [0 1 2 3 4 5]
# reshape
reshaped_arr = arr.reshape(2, 3)
print("\nreshape后的数组:\n", reshaped_arr)
print("原始数组是否改变:", arr) # 原始数组不变
# resize
arr.resize(3, 2)
print("\nresize后的数组:\n", arr)
# 注意:resize是原地操作,原始数组已经被改变了
# flatten
arr_2d = np.array([[1, 2], [3, 4]])
flattened_arr = arr_2d.flatten()
print("\n展平后的数组:", flattened_arr)
print("原始二维数组:\n", arr_2d) # 原始数组不变
| 特性 | 描述 |
|---|---|
| 本质 | NumPy 的核心数据结构,一个高效的多维数组。 |
| 优势 | 高性能(连续内存,向量化计算)、功能强大(丰富的数学函数)、语法简洁(广播机制)。 |
| 创建 | np.array(), np.zeros(), np.ones(), np.arange(), np.linspace() 等。 |
| 核心属性 | shape (形状), ndim (维度), dtype (数据类型), size (元素总数)。 |
| 核心操作 | 索引/切片(arr[0, :])、布尔索引(arr[arr > 0])、数学运算(arr1 + arr2)、广播(不同形状数组运算)。 |
| 修改形状 | reshape() (返回视图), resize() (原地修改), flatten() (返回副本)。 |
掌握 np.ndarray 是使用 Python 进行科学计算、数据分析和机器学习(如使用 Pandas, Scikit-learn, TensorFlow, PyTorch 等)的基石,它将你从低效的 Python 循环中解放出来,让你能专注于算法和逻辑本身。
