本系列是《NumPy 速通》的配套章节。速通是主线,这里是细节。
一切 NumPy 代码的起点:怎么把数据变成 ndarray。本章覆盖所有主流创建方式,以及创建时最容易踩的坑。
从列表 / 元组创建:np.array
把已有的 Python 序列变成 ndarray,用 np.array() 包一下就行:
import numpy as np
# 一维:从列表
scores = np.array([88, 92, 76, 85, 90])
print(scores) # [88 92 76 85 90]
print(type(scores)) # <class 'numpy.ndarray'>
print(scores.dtype) # int64 元素类型
# 从元组也可以
t = np.array((1, 2, 3)) # [1 2 3]
# 二维:嵌套列表 = 表格(行=同学,列=科目)
table = np.array([[88, 92, 76],
[85, 90, 91],
[77, 82, 95]])
print(table.shape) # (3, 3)
打印出来和列表差不多,但底层完全不同:ndarray 把同类型数字紧密排列在连续内存中,运算效率高出几十倍。
np.array 的关键参数
np.array([1, 2, 3], dtype=np.float64) # 指定元素类型
np.array([1, 2, 3], ndmin=2) # 强制至少 2 维 → [[1 2 3]]
np.array([1, 2, 3], copy=True) # 强制复制一份(默认也是复制)
⚠️ 嵌套列表必须"整齐"
np.array([[1, 2], [3]]) # ❌ 报错:各行长度不一致,无法构成矩形
# ValueError: setting an array element with a sequence.
创建矩阵/表格时,每行长度必须相同,否则 NumPy 不知道往哪个维度放。
特殊数组:zeros / ones / full / eye
不想手动敲一堆数字,用工厂函数——它们是创建初始化数组的主流方式:
np.zeros((2, 3)) # 全 0,2 行 3 列 → float64
np.ones((2, 3)) # 全 1
np.full((2, 3), 7) # 全部填 7
np.eye(3) # 3×3 单位矩阵(主对角线为 1,其余 0)
np.eye(3, k=1) # 对角线上移一格(次对角线为 1)
更省事的"照着另一个数组的形状创建":
a = np.array([[1, 2], [3, 4]])
np.zeros_like(a) # 形状同 a,全 0
np.ones_like(a) # 形状同 a,全 1
np.full_like(a, 9) # 形状同 a,全 9
💡
zeros_like这类函数在初始化"结果容器"时非常好用,比如先申请一块同形状内存再往里填。
等差数列:arange vs linspace
生成一系列等距数字,两种思路:
np.arange(0, 10, 2) # [0 2 4 6 8] 指定起点/终点(不含)/步长
np.arange(5) # [0 1 2 3 4] 只给终点,默认从 0 步长 1
np.arange(1, 5, 0.5) # [1. 1.5 2. 2.5 3. 3.5 4. 4.5] 小数步长也行
np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1. ] 0~1 等分 5 份
np.linspace(0, 1, 5, endpoint=False) # 不含终点 1
np.logspace(0, 3, 4) # 对数等距:[1. 10. 100. 1000.]
怎么选:
arange:你知道步长,想要整数下标序列 → 最常用(造循环下标)linspace:你知道要几份,想要浮点区间(画图坐标轴)→ 推荐logspace:跨数量级(如 1、10、100、1000)
⚠️
arange用浮点步长时可能因浮点误差多/少一个元素(如np.arange(0, 1, 0.1)可能到 0.9 就停)。要精确数量用linspace。
空数组:empty / 全零数组的内存陷阱
np.empty((2, 3)) # 申请内存但不初始化 → 里面是"垃圾值"
empty 比 zeros 快(省去清零),但内容是未定义的随机内存残留。新手别直接用,等会儿忘了赋值就翻车。绝大多数情况用 zeros 更安全。
从已有数据/流创建
# 从迭代器
np.fromiter(range(5), dtype=int) # [0 1 2 3 4]
np.fromfunction(lambda i, j: i + j, (3, 3)) # 由函数生成每个元素
# 从文本/文件
np.loadtxt("data.csv", delimiter=",") # 读 CSV
np.genfromtxt("data.csv", delimiter=",", skip_header=1) # 更灵活,可跳过表头
指定数据类型 & 溢出警告
np.array([1, 2, 3], dtype=np.int32) # 32 位整数
np.array([1, 2, 3], dtype=np.float64) # 64 位浮点
np.array([1, 2, 3], dtype=bool) # [True True True]
np.array([1.9, 2.5], dtype=int) # 截断取整 → [1 2](不是四舍五入!)
数组所有元素必须是同一种类型,这正是它快的原因之一。
⚠️ 灵魂警告:静默溢出。Python 原生 int 任意精度,但 NumPy 整数是固定位宽:
np.array([2**63 - 1], dtype=np.int64) + 1 # 不报错!结果是 -9223372036854775808(绕回负数)32 位环境下默认
int32,范围只有 ±21 亿,更容易溢出。数据可能很大或要算小数时,显式dtype=np.float64。
小结
| 目的 | 用哪个 |
|---|---|
| 把已有列表转成数组 | np.array(list) |
| 全 0 / 全 1 / 填固定值 | np.zeros / np.ones / np.full |
| 单位矩阵 | np.eye |
| 整数序列 | np.arange |
| 等分浮点区间 | np.linspace |
| 造随机初始化 | np.random.default_rng().random(...)(见第 12 章) |
创建是一切的基础——后面所有索引、运算、统计都发生在这些数组上。下一章看怎么"体检"一个数组(shape / dtype / size)。
下一篇:第 2 章 数组属性