Numpy 详解
Numpy 详解
一、Numpy优势
学习目标
- 了解Numpy运算速度上的优势
- 知道Numpy的数组内存块风格
- 知道Numpy的并行化运算
1 Numpy介绍
Numpy(Numerical Python) 是一个开源的Python科学计算库,专门用于快速处理任意维度的数组。
Numpy使用ndarray对象来处理多维数组,该对象是一个快速而灵活的大数据容器。相比Python原生的列表,Numpy在数值计算方面更加高效简洁。
import numpy as np
# 示例:创建一个二维数组(学生成绩表)
score = np.array([[80, 89, 86, 67, 79],
[78, 97, 89, 67, 81],
[90, 94, 78, 67, 74]])
print(score)
# 输出:
# [[80 89 86 67 79]
# [78 97 89 67 81]
# [90 94 78 67 74]]
2 ndarray介绍
NumPy provides an N-dimensional array type, the ndarray, which describes a collection of “items” of the same type.
NumPy提供了一个N维数组类型ndarray,它描述了相同类型的"items"的集合。
# nd= N-dimensional array (N维数组)
# 例如:2行3列的二维数组
arr_2d = np.array([[1, 2, 3],
[4, 5, 6]])
print(arr_2d.shape) # (2, 3)
3 ndarray与Python原生list运算效率对比
Numpy专门针对ndarray的操作和运算进行了设计,数组的存储效率和输入输出性能远优于Python中的嵌套列表。数组越大,Numpy的优势就越明显。
import random
import time
import numpy as np
# Python列表:1亿个随机数求和
a = [random.random() for i in range(100000000)]
start = time.time()
sum_list = sum(a)
print(f"Python列表求和耗时: {time.time() - start:.2f}秒")
# NumPy数组求和
b = np.array(a)
start = time.time()
sum_np = np.sum(b)
print(f"NumPy求和耗时: {time.time() - start:.2f}秒")
# 结果示例:Python约1.1秒,NumPy约0.1秒,快10倍以上
结论:在机器学习等需要大量数据运算的场景中,Numpy的高效性能至关重要。
4 ndarray的优势
4.1 内存块风格
| 存储方式 | Python列表 | ndarray |
|---|---|---|
| 存储模式 | 分离式存储 | 一体式存储 |
| 元素类型 | 类型任意 | 类型必须相同 |
| 内存连续性 | 不连续,需寻址 | 连续存储,批量操作快 |
# Python列表:元素类型可以不同
py_list = [1, 2.5, "hello", True] # 各种类型混搭
# NumPy数组:元素类型必须相同
np_arr = np.array([1, 2, 3, 4]) # 必须是同类型
print(np_arr.dtype) # int64
为什么连续存储更快?
- 连续内存使CPU缓存预取更高效
- 无需像列表那样通过指针链查找下一个元素
- 可以使用SIMD指令集进行向量化计算
4.2 并行化运算(向量化运算)
Numpy内置并行运算功能,当系统有多个CPU核心时,会自动并行计算。
# Numpy自动使用多核并行计算
arr = np.random.rand(1000000)
result = np.sum(arr) # 底层自动并行
4.3 底层C语言,高效GIL-free
Numpy底层使用C语言编写,**解除了GIL(全局解释器锁)**的限制,数组操作速度不受Python解释器限制,效率远高于纯Python代码。
5 小结
| 知识点 | 说明 |
|---|---|
| Numpy定位 | 开源的Python科学计算库 |
| 核心对象 | ndarray - N维数组类型 |
| 优势1 | 内存块风格 - 一体式存储,类型一致 |
| 优势2 | 并行化运算 - 自动多核并行 |
| 优势3 | C语言底层 - 解除GIL,高效计算 |
二、N维数组-ndarray
学习目标
- 说明数组的属性,形状、类型
1 ndarray的属性
| 属性 | 说明 | 示例 |
|---|---|---|
ndarray.shape |
数组维度的元组 | (3, 4) 表示3行4列 |
ndarray.ndim |
数组维数 | 1表示一维,2表示二维 |
ndarray.size |
数组中的元素总数量 | 12表示共12个元素 |
ndarray.itemsize |
每个元素的字节大小 | int64返回8 |
ndarray.dtype |
数组元素的数据类型 | int64, float32等 |
arr = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
print(arr.shape) # (3, 4) - 3行4列
print(arr.ndim) # 2 - 二维数组
print(arr.size) # 12 - 共12个元素
print(arr.itemsize) # 8 - int64每个元素8字节
print(arr.dtype) # int64 - 数据类型
2 ndarray的形状
一维数组
arr_1d = np.array([1, 2, 3, 4])
print(arr_1d.shape) # (4,)
二维数组
arr_2d = np.array([[1, 2, 3],
[4, 5, 6]])
print(arr_2d.shape) # (2, 3) - 2行3列
三维数组
arr_3d = np.array([[[1, 2, 3],
[4, 5, 6]],
[[7, 8, 9],
[10, 11, 12]]])
print(arr_3d.shape) # (2, 2, 3) - 2个平面,每个平面2行3列
形象理解
一维数组 [1, 2, 3, 4]:
┌───┬───┬───┬───┐
│ 1 │ 2 │ 3 │ 4 │
└───┴───┴───┴───┘
二维数组 [[1, 2], [3, 4]]:
┌───┬───┐
│ 1 │ 2 │
├───┼───┤
│ 3 │ 4 │
└───┴───┘
三维数组:可以理解为多层二维数组的叠加
3 ndarray的类型(dtype)
| 类型代码 | 名称 | 描述 | 字节大小 |
|---|---|---|---|
'b' |
np.bool_ |
布尔类型 | 1 |
'i' |
np.int8 |
8位整数 | 1 |
'i2' |
np.int16 |
16位整数 | 2 |
'i4' |
np.int32 |
32位整数(最常用) | 4 |
'i8' |
np.int64 |
64位整数 | 8 |
'u' |
np.uint8 |
无符号8位整数 | 1 |
'u4' |
np.uint32 |
无符号32位整数 | 4 |
'f2' |
np.float16 |
半精度浮点 | 2 |
'f4' |
np.float32 |
单精度浮点 | 4 |
'f8' |
np.float64 |
双精度浮点(默认) | 8 |
'c8' |
np.complex64 |
复数(两个float32) | 8 |
'c16' |
np.complex128 |
复数(两个float64) | 16 |
'O' |
np.object_ |
Python对象 | - |
'S' |
np.string_ |
字节字符串 | - |
'U' |
np.unicode_ |
Unicode字符串 | - |
示例
# 创建时指定数据类型
arr_int32 = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int32)
print(arr_int32.dtype) # int32
# 创建字符串数组
arr_str = np.array(['hello', 'world'], dtype=np.string_)
print(arr_str) # [b'hello' b'world']
# 默认类型
int_arr = np.array([1, 2, 3]) # 默认int64
float_arr = np.array([1.0, 2.0]) # 默认float64
print(int_arr.dtype, float_arr.dtype) # int64 float64
4 总结
ndarray的核心属性:
arr = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32)
print(arr.shape) # (2, 3) - 形状
print(arr.ndim) # 2 - 维度
print(arr.size) # 6 - 元素数
print(arr.dtype) # float32 - 类型
print(arr.itemsize) # 4 - 元素字节数
三、基本操作
学习目标
- 理解数组的各种生成方法
- 应用数组的索引机制实现数组的切片获取
- 应用维度变换实现数组的形状改变
- 应用类型变换实现数组类型改变
1 生成数组的方法
1.1 生成0和1的数组
# 生成全1数组
ones = np.ones((3, 4)) # 3行4列的全1数组
print(ones)
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]]
# 指定数据类型
ones_int = np.ones((2, 3), dtype=np.int32)
print(ones_int.dtype) # int32
# 生成全0数组
zeros = np.zeros((2, 3))
print(zeros)
# [[0. 0. 0.]
# [0. 0. 0.]]
# 根据已有数组生成
arr = np.array([[1, 2], [3, 4]])
ones_like = np.ones_like(arr) # 与arr形状相同的全1数组
zeros_like = np.zeros_like(arr) # 与arr形状相同的全0数组
应用场景:
np.zeros()- 初始化数组、创建掩码np.ones()- 创建全1数组、初始化权重
1.2 从现有数组生成
a = np.array([[1, 2, 3], [4, 5, 6]])
# 深拷贝 - 创建独立副本
a1 = np.array(a)
a1[0, 0] = 100
print(a[0, 0]) # 1,原始数组不受影响
# 浅拷贝 - 共享数据视图
a2 = np.asarray(a)
a2[0, 0] = 100
print(a[0, 0]) # 100,原始数组被修改
区别:
np.array()- 总是复制数据(深拷贝)np.asarray()- 如果输入已经是数组,不复制(浅拷贝)
1.3 生成固定范围的数组
np.linspace() - 等差数组(指定数量)
# 从0到10,生成5个等差数
arr = np.linspace(0, 10, 5)
print(arr) # [ 0. 2.5 5. 7.5 10. ]
# 包括终点
arr = np.linspace(0, 100, 11) # 0到100,生成11个数
print(arr) # [ 0. 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.]
# 不包括终点
arr = np.linspace(0, 10, 5, endpoint=False)
print(arr) # [0. 2. 4. 6. 8.]
np.arange() - 等差数组(指定步长)
# 从0到10,步长2
arr = np.arange(0, 10, 2)
print(arr) # [0 2 4 6 8]
# 从1到10
arr = np.arange(1, 11)
print(arr) # [ 1 2 3 4 5 6 7 8 9 10]
# 负数步长
arr = np.arange(10, 0, -1)
print(arr) # [10 9 8 7 6 5 4 3 2 1]
np.logspace() - 等比数列
# 生成10^0到10^2(即1到100)的等比数列,共3个数
arr = np.logspace(0, 2, 3)
print(arr) # [ 1. 10. 100.]
# 常用于创建对数刻度的坐标
x = np.logspace(0, 3, 100) # 10^0到10^3之间100个点
对比:
| 函数 | 生成方式 | 适用场景 |
|---|---|---|
np.linspace(0, 10, 5) |
指定数量,自动计算步长 | 需要精确控制点数 |
np.arange(0, 10, 2) |
指定步长,自动计算数量 | 需要固定间隔 |
np.logspace(0, 2, 3) |
等比数列 | 对数刻度坐标 |
1.4 生成随机数组
# 均匀分布 [0.0, 1.0)
np.random.rand(3, 2) # 3行2列的随机数
np.random.rand(10) # 10个随机数
# 均匀分布 [low, high)
np.random.randint(0, 10, size=(3, 4)) # 0到10之间,整数,3行4列
np.random.randint(1, 100, 10) # 1到100之间,10个整数
# 标准正态分布(均值0,标准差1)
np.random.randn(100) # 100个符合标准正态分布的数
# 正态分布(自定义均值和标准差)
np.random.normal(170, 5, (100,)) # 均值170,标准差5,100个数
np.random.normal(0, 1, (3, 3)) # 3x3的标准正态分布矩阵
# 设置随机种子(使结果可复现)
np.random.seed(42)
print(np.random.rand(5)) # 每次运行结果相同
2 数组的索引、切片
基本索引
arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 索引格式:arr[行, 列]
print(arr[0, 0]) # 1 - 第1行第1列
print(arr[1, 2]) # 6 - 第2行第3列
print(arr[-1, -1]) # 9 - 最后一行最后一列
切片操作
arr = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
# 切片格式:arr[起始:结束:步长, 起始:结束:步长]
# 取第1行
print(arr[0, :]) # [1 2 3 4]
# 取第1列
print(arr[:, 0]) # [1 5 9]
# 取前2行
print(arr[0:2, :]) # [[1 2 3 4]
# [5 6 7 8]]
# 取前2列
print(arr[:, 0:2]) # [[ 1 2]
# [ 5 6]
# [ 9 10]]
# 跳过行/列
print(arr[::2, ::2]) # [[1 3]
# [9 11]]
布尔索引
arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 找出大于5的元素
mask = arr > 5
print(mask)
# [[False False False]
# [False False True]
# [ True True True]]
print(arr[mask]) # [6 7 8 9]
# 直接赋值
arr[arr > 5] = 0
print(arr)
# [[1 2 3]
# [4 5 0]
# [0 0 0]]
三维数组索引
arr_3d = np.array([[[1, 2], [3, 4]],
[[5, 6], [7, 8]]])
print(arr_3d.shape) # (2, 2, 2)
# 索引格式:[平面, 行, 列]
print(arr_3d[0, 0, 0]) # 1 - 第1个平面,第1行,第1列
print(arr_3d[1, 1, 1]) # 8 - 第2个平面,第2行,第2列
# 取整个第1个平面
print(arr_3d[0]) # [[1 2]
# [3 4]]
3 形状修改
reshape() - 返回视图
arr = np.arange(12) # [0 1 2 3 4 5 6 7 8 9 10 11]
print(arr.shape) # (12,)
# 改为3行4列(元素总数不变)
new_arr = arr.reshape(3, 4)
print(new_arr)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# -1自动计算维度
arr.reshape(-1, 4) # 自动计算行数:3行4列
arr.reshape(3, -1) # 自动计算列数:3行4列
arr.reshape(-1) # 展平为一维
resize() - 修改原数组
arr = np.arange(12)
arr.resize(3, 4) # 直接修改原数组
print(arr)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
T(转置)
arr = np.arange(6).reshape(2, 3)
print(arr)
# [[0 1 2]
# [3 4 5]]
print(arr.T)
# [[0 3]
# [1 4]
# [2 5]]
# 高维数组转置
arr_3d = np.arange(24).reshape(2, 3, 4) # 2个平面,3行,4列
print(arr_3d.T.shape) # (4, 3, 2) - 完全反转维度
4 类型修改
astype() - 类型转换
arr = np.array([1.5, 2.7, 3.3])
# 转为整数
int_arr = arr.astype(np.int32)
print(int_arr) # [1 2 3]
# 转为字符串
str_arr = arr.astype(str)
print(str_arr) # ['1.5' '2.7' '3.3']
# 转为布尔
bool_arr = np.array([0, 1, 2, 3]).astype(bool)
print(bool_arr) # [False True True True]
tobytes() - 转为字节串
arr = np.array([[1, 2], [3, 4]])
bytes_data = arr.tobytes()
print(bytes_data) # b'\x01\x00\x00\x00...'
应用:网络传输、数据持久化
5 数组去重
np.unique()
arr = np.array([1, 2, 2, 3, 3, 3, 4])
# 基本去重
unique_vals = np.unique(arr)
print(unique_vals) # [1 2 3 4]
# 二维数组去重(自动展平)
arr_2d = np.array([[1, 2, 3], [2, 3, 4]])
print(np.unique(arr_2d)) # [1 2 3 4]
# 返回索引
arr = np.array(['b', 'a', 'c', 'b'])
unique, indices = np.unique(arr, return_index=True)
print(indices) # [1 0 2] - 首次出现的位置
# 返回出现次数
unique, counts = np.unique(arr, return_counts=True)
print(counts) # [2 1 1] - 每个值出现的次数
6 小结
| 功能 | 函数 | 说明 |
|---|---|---|
| 生成0/1 | np.ones() / np.zeros() |
创建全0或全1数组 |
| 拷贝 | np.array() / np.asarray() |
深拷贝 vs 浅拷贝 |
| 范围数组 | np.linspace() / np.arange() |
等差数列 |
| 随机数组 | np.random.rand() / randint() / normal() |
随机数生成 |
| 索引切片 | arr[行, 列] |
先行后列 |
| 形状修改 | reshape() / resize() / .T |
形状变换 |
| 类型修改 | astype() |
类型转换 |
| 去重 | np.unique() |
去除重复元素 |
四、ndarray运算
学习目标
- 应用数组的通用判断函数
- 应用np.where实现数组的三元运算
1 逻辑运算
score = np.random.randint(40, 100, (10, 5)) # 10名学生,5门课成绩
print(score)
# [[52 85 67 73 91]
# [88 92 45 78 65]
# ...]
# 逻辑判断:成绩大于60
print(score > 60)
# [[False True True True True]
# [ True True False True True]
# ...]
# 布尔索引赋值:大于60的置为1
score[score > 60] = 1
print(score)
# [[52 1 1 1 1]
# [ 1 1 45 1 1]
# ...]
2 通用判断函数
np.all() - 所有元素都满足条件
# 判断所有成绩是否都大于60
score = np.random.randint(40, 100, (5, 3))
result = np.all(score > 60)
print(f"全部及格?{result}") # False 或 True
# 按维度判断
print(np.all(score > 60, axis=0)) # 每门课是否全部及格
print(np.all(score > 60, axis=1)) # 每个学生是否全部及格
np.any() - 至少有一个元素满足条件
# 判断是否有90分以上的成绩
result = np.any(score > 90)
print(f"有90分以上?{result}") # False 或 True
# 按维度判断
print(np.any(score > 90, axis=0)) # 哪几门课有90分以上的
print(np.any(score > 90, axis=1)) # 哪些学生有90分以上的
区别:
| 函数 | 逻辑 | 返回True的条件 |
|---|---|---|
np.all() |
全真才真 | 所有元素都满足条件 |
np.any() |
有真即真 | 至少有一个元素满足条件 |
3 np.where(三元运算符)
基本用法
temp = np.array([58, 72, 85, 91, 45])
# 条件满足返回1,否则返回0
result = np.where(temp > 60, 1, 0)
print(result) # [0 1 1 1 0]
复合逻辑
# np.logical_and - 逻辑与
np.where(np.logical_and(temp > 60, temp < 90), 1, 0)
# 结果:[0 1 1 0 0] - 60到90之间(不含)的为1
# np.logical_or - 逻辑或
np.where(np.logical_or(temp > 90, temp < 60), 1, 0)
# 结果:[1 0 0 1 1] - 大于90或小于60的为1
# np.logical_not - 逻辑非
np.where(np.logical_not(temp > 60), 1, 0)
# 结果:[1 0 0 0 1] - 不大于60的为1
嵌套where
# 成绩分级:<60不及格,60-80及格,>80优秀
temp = np.array([45, 72, 85, 91])
result = np.where(temp < 60, '不及格',
np.where(temp < 80, '及格', '优秀'))
print(result) # ['不及格' '及格' '优秀' '优秀']
4 统计运算
基本统计函数
arr = np.array([[4, 2, 5],
[1, 8, 3],
[6, 7, 9]])
print(np.min(arr)) # 1 - 最小值
print(np.max(arr)) # 9 - 最大值
print(np.mean(arr)) # 5.0 - 平均值
print(np.median(arr)) # 5.0 - 中位数
print(np.std(arr)) # 2.58... - 标准差
print(np.var(arr)) # 6.67... - 方差
按维度统计
arr = np.array([[4, 2, 5],
[1, 8, 3]])
# axis=0:沿着列操作(跨行)
print(np.min(arr, axis=0)) # [1 2 3] - 每列的最小值
# axis=1:沿着行操作(跨列)
print(np.min(arr, axis=1)) # [2 1] - 每行的最小值
argmax/argmin - 索引位置
arr = np.array([3, 1, 4, 1, 5, 9, 2, 6])
print(np.argmax(arr)) # 5 - 最大值9的下标
print(np.argmin(arr)) # 1 - 最小值1的下标
# 二维数组
arr_2d = np.array([[4, 2, 5],
[1, 8, 3]])
print(np.argmax(arr_2d, axis=0)) # [0 1 0] - 每列最大值的行索引
print(np.argmax(arr_2d, axis=1)) # [2 1] - 每行最大值的列索引
常用统计指标说明
| 指标 | 说明 | 公式 |
|---|---|---|
| 均值(mean) | 所有数值的平均值 | sum/n |
| 中位数(median) | 排序后位于中间的数 | - |
| 方差(var) | 数值与均值的平方偏差 | sum((x-mean)²)/n |
| 标准差(std) | 方差的平方根 | sqrt(var) |
方差 vs 标准差:
- 方差越大,数据越分散
- 标准差与原数据单位相同,更易理解
5 小结
| 运算类型 | 函数 | 说明 |
|---|---|---|
| 逻辑运算 | arr > 60 |
返回布尔数组 |
| 布尔赋值 | arr[arr > 60] = 1 |
条件赋值 |
| 全真判断 | np.all() |
所有元素都满足 |
| 有真判断 | np.any() |
至少一个满足 |
| 三元运算 | np.where() |
条件赋值 |
| 复合逻辑 | np.logical_and/or/not |
逻辑组合 |
| 统计函数 | min/max/mean/median/std/var |
基础统计 |
| 索引函数 | argmax/argmin |
最大/小值位置 |
五、数组间运算
学习目标
- 知道数组与数之间的运算
- 知道数组与数组之间的运算
- 说明数组间运算的广播机制
1 数组与数的运算
数组与标量(单个数字)运算时,每个元素都分别进行运算。
arr = np.array([[1, 2, 3],
[4, 5, 6]])
print(arr + 1) # [[2 3 4]
# [5 6 7]]
print(arr - 1) # [[0 1 2]
# [3 4 5]]
print(arr * 2) # [[2 4 6]
# [8 10 12]]
print(arr / 2) # [[0.5 1. 1.5]
# [2. 2.5 3. ]]
print(arr ** 2) # [[ 1 4 9]
# [16 25 36]]
print(arr % 2) # [[1 0 1]
# [0 1 0]]
2 数组与数组的运算
形状相同,直接运算
a = np.array([[1, 2, 3],
[4, 5, 6]])
b = np.array([[10, 20, 30],
[40, 50, 60]])
print(a + b) # [[11 22 33]
# [44 55 66]]
print(a * b) # [[ 10 40 90]
# [160 250 360]]
形状不同,需要广播
3 广播机制
什么是广播?
当两个数组形状不同时,NumPy会自动将较小的数组"广播"到较大数组的形状,使它们能够进行运算。
广播规则
规则1:维度数不同,在前面补1维
a = np.array([[1, 2, 3]]) # shape: (1, 3)
b = np.array([[1], [2], [3]]) # shape: (3, 1)
# a 广播为 (3, 3)
# b 广播为 (3, 3)
print(a + b)
# [[2 3 4]
# [3 4 5]
# [4 5 6]]
规则2:从最后一个维度开始比较
a = np.array([[1, 2, 3]]) # shape: (1, 3)
b = np.array([[1], [2], [3]]) # shape: (3, 1)
# 从后向前比较:
# 第2维:3 vs 1 → 可以广播(1会扩展为3)
# 第1维:1 vs 3 → 可以广播(1会扩展为3)
# 结果形状:(3, 3)
规则3:维度长度必须相同或为1
# 可以广播的例子
a = np.ones((3, 4)) # shape: (3, 4)
b = np.ones((1, 4)) # shape: (1, 4) → 广播为 (3, 4)
# 可以广播的例子
a = np.ones((3, 4)) # shape: (3, 4)
b = 5 # 标量 → 广播为 (3, 4)
# 不能广播的例子
a = np.ones((3, 4)) # shape: (3, 4)
b = np.ones((3, 5)) # shape: (3, 5) → 4≠5,报错
广播示例
# 示例1:行向量与列向量相加
row = np.array([1, 2, 3]) # shape: (3,)
col = np.array([[1], [2], [3]]) # shape: (3, 1)
print(row + col)
# [[2 3 4]
# [3 4 5]
# [4 5 6]]
# 示例2:矩阵与标量相加
mat = np.array([[1, 2, 3],
[4, 5, 6]])
print(mat + 10)
# [[11 12 13]
# [14 15 16]]
# 示例3:三维数组广播
a = np.ones((2, 3, 4)) # shape: (2, 3, 4)
b = np.ones((3, 4)) # shape: (3, 4) → 广播为 (2, 3, 4)
c = np.ones((1, 4)) # shape: (1, 4) → 广播为 (2, 3, 4)
形象理解广播
a (3x1): b (1x3): a + b (3x3):
┌───┐ ┌───┬───┬───┐ ┌───┬───┬───┐
│ 1 │ │ 1 │ 2 │ 3 │ │ 2 │ 3 │ 4 │
├───┤ └───┴───┴───┘ ├───┼───┼───┤
│ 2 │ + = │ 3 │ 4 │ 5 │
├───┤ │ 4 │ 5 │ 6 │
│ 3 │ └───┴───┴───┘
└───┘
4 小结
| 运算类型 | 说明 |
|---|---|
| 数组+标量 | 每个元素与标量运算 |
| 数组+数组(形状相同) | 对应元素直接运算 |
| 数组+数组(形状不同) | 自动广播,维度长度必须相同或为1 |
广播的核心:将较小的数组在缺失的维度上复制扩展,直到与较大数组形状匹配。
更多推荐


所有评论(0)