array 从列表造,zeros/ones/full 造填充值,eye 造单位矩阵。 zeros 和 ones 默认是 float64。做整数运算要写 dtype=int。 empty 不是「全是 0」,它只是不初始化,里面的值是不可预测的残留。
上一篇讲了数组是什么。这一篇讲怎么造:从列表、从填充值、从形状模板。 七个函数覆盖九成场景,其中最常用的还是 array 和 zeros。
一、从列表来:array
np.array([1, 2, 3]) 是一维,形状 (3,)。
np.array([[1, 2], [3, 4]]) 是二维,形状 (2, 2),元素 4 个。
一维形状是 (3,),不是 (3, 1)。这两个完全不一样,混了会报形状错。
(3,) 是一行三个数,(3, 1) 是三行一列。做矩阵乘法时这个差别是致命的。
二、填充值:zeros、ones、full
np.zeros(5) 给五个 0.0,np.ones((2, 3)) 给两行三列的 1.0。
np.full((2, 2), 7) 给两行两列全是 7。
三个函数默认都是 float64。要整数必须写 dtype=int。
忘了 dtype 的后果:后面按整数取模、按整数分组,全都会因为 1.0 而不是 1 出问题。
三、empty 和 eye
np.empty(3) 不初始化,里面是内存里的残留值,可能是任意数。
empty 不是「全是 0」。它只是「不花时间填」,值完全不可预测。
np.eye(3) 是 3 乘 3 的单位矩阵,对角线 1、其余 0。
单位矩阵在矩阵运算里相当于数字 1:任何矩阵乘它都不变。
四、照抄形状:_like 系列
np.zeros_like(A) 造一个和 A 同形状的全 0 数组。
还有 ones_like、full_like,用法一样。
它们会连 dtype 一起照抄。A 是 int64,出来的也是 int64。
这就是它和 zeros(A.shape) 的差别:后者默认 float。
五、七个函数一张表
| 要什么 | 用哪个 | 注意 |
|---|---|---|
| 从列表造 | array | 类型自动推 |
| 全 0 | zeros | 默认 float |
| 全 1 | ones | 默认 float |
| 全某值 | full | 形状要传元组 |
| 不初始化 | empty | 值是残留 |
| 单位矩阵 | eye | 方阵 |
| 照抄形状 | zeros_like 等 | 连类型一起抄 |
七个函数,记住了就不用每次去查文档。
六、动手 Demo:创建数组的几种方式
七个造法各造一个,把形状、维度、元素个数都打出来。 重点看 zeros 的默认类型和 _like 的类型继承。
import numpy as np
A = np.array([1, 2, 3])
B = np.array([[1, 2], [3, 4]])
print("一维 %s 形状 %s 维度 %d" % (A, A.shape, A.ndim))
print("二维 形状 %s 维度 %d 元素 %d" % (B.shape, B.ndim, B.size))
print("zeros %s %s" % (np.zeros(5), np.zeros(5).dtype))
print("dtype=int %s" % (np.zeros(3, dtype=int),))
print("ones %s" % (np.ones((2, 3)).shape,))
print("full %s" % np.full((2, 2), 7).tolist())
print("eye %s" % np.eye(3, dtype=int).tolist())
print("empty %s(每次可能不同)" % (np.empty(3),))
T = np.arange(6).reshape(2, 3)
print("zeros_like %s %s" % (np.zeros_like(T).shape, np.zeros_like(T).dtype))
print("full_like %s" % np.full_like(T, 9).tolist())
实跑输出:
--------------------------------------------------------------------
创建数组的几种方式
--------------------------------------------------------------------
① 从列表来:array
--------------------------------------------------------------------
一维:[1 2 3],形状 (3,),维度 1。
二维:形状 (2, 2),维度 2,元素个数 4。
[1, 2]
[3, 4]
! 形状是个元组,一维是 (3,),不是 (3, 1)。这两个不一样。
② 全 0、全 1、全某个值
--------------------------------------------------------------------
zeros(5):[0. 0. 0. 0. 0.]
ones((2, 3)):形状 (2, 3),全是 1.0。
full((2, 2), 7):[ [7, 7], [7, 7]]
默认是 float64,想要整数得写 dtype=int:[0 0 0]。
! zeros 和 ones 的默认类型是小数。做整数运算时忘了 dtype,结果是 1.0 不是 1。
③ 空数组与单位矩阵
--------------------------------------------------------------------
empty(3) 不给初值,里面是内存里的残留:[0. 0. 0.]。
eye(3) 是单位矩阵,对角线是 1:
[1, 0, 0]
[0, 1, 0]
[0, 0, 1]
eye 做矩阵运算时常用,比如求逆、解方程。
! empty 不是「全是 0」,它只是「不初始化」。里面的值是不可预测的,别拿来当默认值。
④ 像另一个数组的形状
--------------------------------------------------------------------
原数组形状 (2, 3)。
zeros_like → 同形状全 0,(2, 3)。
ones_like → 同形状全 1,(2, 3)。
full_like(A, 9) → 同形状全 9,类型也照抄原数组。
! _like 系列会连 dtype 一起照抄。这个是它和 zeros(shape) 的差别。
⑤ 一张表记完
--------------------------------------------------------------------
| 要什么 | 用哪个 | 注意 |
|---|---|---|
| 从列表造 | array | 类型自动推 |
| 全 0 | zeros | 默认 float |
| 全 1 | ones | 默认 float |
| 全某值 | full | 要传形状元组 |
| 不初始化 | empty | 值是残留 |
| 单位矩阵 | eye | 方阵 |
| 照抄形状 | zeros_like 等 | 连类型一起抄 |
七个函数,覆盖了九成「造数组」的场景。
np.empty(3) 打出来的值每次跑都可能不一样,这不是 bug,是「没初始化」。
zeros_like 的类型跟原数组一致,zeros(shape) 的类型默认 float64。
30 秒实验
- 把 np.zeros(5) 的 dtype 改成 int,看输出少了那个小数点。
- 造一个 np.empty(5),连跑三次,看三次的值一样不一样。
- 想一想:为什么一维形状是 (3,) 而不是 (3, 1)?
常见误区
- 以为 zeros 给整数:默认 float,后面按整数用会出问题。
- 把 empty 当全 0 用:里面是残留值,可能是个巨大的数。
- 形状写成 3 而不是 (3,):一维传整数没问题,二维必须传元组。
- 混淆 (3,) 和 (3, 1):元素个数一样,形状完全不同,矩阵乘法会报错。
自测三问(点开对答案)
1. zeros(3) 和 zeros(3, dtype=int) 有什么区别? —— 前者是 [0. 0. 0.] 浮点,后者是 [0 0 0] 整数。默认是浮点。 2. empty 和 zeros 有什么区别? —— empty 不初始化,值是不可预测的残留;zeros 真的把每个位置填成 0。 3. zeros_like 和 zeros(A.shape) 有什么区别? —— 前者连 dtype 一起照抄 A,后者默认 float64。array 要一个个给值太累。下一篇讲怎么按范围批量造:arange 和 linspace。
- ☐ (本篇完,下一篇 6.3 从数值范围创建数组)