本系列是《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 章 数组属性