
import numpy as np
N, M, P = map(int, input().split())
arr1 = [list(map(int, input().split())) for _ in range(N)]
arr2 = [list(map(int, input().split())) for _ in range(M)]
arr1 = np.array(arr1)
arr2 = np.array(arr2)
print(np.concatenate((arr1, arr2), axis=0))
axis 这个参数到底是什么意思
你现在可以先把 axis 暂时理解成一句最实用的话:
axis 决定你“沿着哪一个方向去操作数组”。
在 numpy.concatenate() 里面,axis 的意思就是:
你要沿着哪一个轴,把多个数组接起来。
先看你给的这两个数组
array_1 = numpy.array([[1,2,3],[0,0,0]])
array_2 = numpy.array([[0,0,0],[7,8,9]])
把它们写整齐一点,就是:
array_1 =
[[1 2 3]
[0 0 0]]
array_2 =
[[0 0 0]
[7 8 9]]
这两个数组的形状都是:
(2, 3)
表示:
- 2 行
- 3 列
二维数组里,axis=0 和 axis=1 怎么理解
对于二维数组,你可以先这样记:
axis=0:按上下方向处理,也就是“行的方向”axis=1:按左右方向处理,也就是“列的方向”
你也可以把它记成:
axis=0:往下堆axis=1:往右拼
这是最适合初学者的记法。
为什么你这里 axis=1 可以成功
你的代码是:
print(numpy.concatenate((array_1, array_2), axis=1))
这里的 axis=1 表示:
把两个数组按列方向拼接,也就是左右拼接。
所以效果相当于:
[[1 2 3] + [0 0 0]
[0 0 0]] [7 8 9]]
左右拼起来以后,就是:
[[1 2 3 0 0 0]
[0 0 0 7 8 9]]
所以输出结果是:
[[1 2 3 0 0 0]
[0 0 0 7 8 9]]
它为什么能成功,核心原因是什么
因为:
你使用的是 axis=1
也就是左右拼接。
那么左右拼接时,要求是什么?
要求是:
行数必须一样。
因为你是一行对一行地往右接。
而你的两个数组:
array_1.shape = (2, 3)array_2.shape = (2, 3)
它们的行数都是 2,完全一致。
所以可以成功拼接。
这里最容易混淆的一点
很多人会以为:
“axis=1 是不是要求第 1 维必须相同?”
这个想法不够直观,初学时很容易绕晕。
你现在先用更直白的方式理解:
如果是 axis=1,说明你要左右拼接
那么左右拼接时:
- 行数必须相同
- 列数可以增加
你这里刚好满足这一点,所以成功。
拼接后:
- 原来每个数组 2 行 3 列
- 左右拼接后变成 2 行 6 列
所以结果形状是:
(2, 6)
如果改成 axis=0 会发生什么
如果你写:
print(numpy.concatenate((array_1, array_2), axis=0))
那就变成上下拼接。
相当于:
[[1 2 3]
[0 0 0]]
[[0 0 0]
[7 8 9]]
上下接起来后就是:
[[1 2 3]
[0 0 0]
[0 0 0]
[7 8 9]]
这时结果形状变成:
(4, 3)
因为:
- 行数变多了:2 + 2 = 4
- 列数不变:还是 3
所以 axis 到底该怎么判断
你以后看到 concatenate,直接先问自己:
我要的是“上下接”,还是“左右接”?
如果是:
上下接
就写:
axis=0
要求:
列数相同
左右接
就写:
axis=1
要求:
行数相同
用你这道题和你上一道题对比一下,就会特别清楚
你上一道题
前一个数组形状是:
(4, 2)
后一个数组形状是:
(3, 2)
你当时写了:
axis=1
也就是左右拼接。
但左右拼接要求行数相同。
可是:
- 一个 4 行
- 一个 3 行
行数不同,所以报错。
这一次这道题
两个数组都是:
(2, 3)
你写的是:
axis=1
左右拼接要求行数相同。
这里两个数组都是 2 行,所以成功。
再进一步:axis 本质上是“维度编号”
如果你想稍微更正式一点理解:
一个二维数组的形状写成:
(行数, 列数)
比如 (2, 3):
- 第 0 维大小是 2,也就是 2 行
- 第 1 维大小是 3,也就是 3 列
所以:
axis=0:沿着第 0 维方向操作axis=1:沿着第 1 维方向操作
但是对于初学者来说,这个说法不如“上下接 / 左右接”好记。
所以你现阶段优先记住这个就够了:
axis=0:上下拼axis=1:左右拼
一张非常实用的小表
| 写法 | 直观理解 | 结果变化 | 需要满足的条件 |
|---|---|---|---|
axis=0 | 上下拼接 | 行数增加 | 列数相同 |
axis=1 | 左右拼接 | 列数增加 | 行数相同 |
这个表你后面做题时会非常有用。
本题小结
你这段代码之所以能成功:
print(numpy.concatenate((array_1, array_2), axis=1))
原因就是:
axis=1表示左右拼接- 左右拼接要求两个数组的行数相同
array_1和array_2都是 2 行- 所以可以成功拼接
- 拼接后结果从
(2, 3)变成(2, 6)
最终结果是:
[[1 2 3 0 0 0]
[0 0 0 7 8 9]]
给你一个非常小的练习
你自己判断一下下面这两个能不能拼:
a.shape = (3, 2)
b.shape = (3, 4)
请你试着回答:
1. 用 axis=0 能不能拼?
2. 用 axis=1 能不能拼?
3. 如果能拼,结果形状是什么?
提示:
axis=0看列数axis=1看行数
为什么叫 axis=0、axis=1,而不是直接写成 row 或 col
这是一个非常好的问题。很多初学者第一次接触 NumPy 的时候,都会觉得这里有点别扭:
“明明二维数组就是行和列,为什么不直接写 row、col,非要写成 axis=0、axis=1 呢?”
这其实不是 NumPy 故意绕,而是因为它面对的对象不只是二维表格,而是更一般的 多维数组。一旦你把这个背景想清楚,axis 这个名字就会变得很自然。
先说结论:row 和 col 只适合二维,axis 适合任意维度
如果一个数组永远只有二维,那么用 row 和 col 确实很直观:
- row 表示行
- col 表示列
但是 NumPy 里的数组,不一定只有二维。
它可能是:
- 一维数组
- 二维数组
- 三维数组
- 四维数组
- 更多维数组
这时候,如果还用 row 和 col,就会立刻出问题。
因为:
- 一维数组没有“行列”这种说法
- 三维数组不止“行列”两个方向
- 更高维数组更不可能只靠
row和col表达清楚
所以 NumPy 需要一个更通用的概念,这个概念就是:
第 0 轴、第 1 轴、第 2 轴……
也就是 axis=0、axis=1、axis=2。
axis 本质上是什么意思
你可以把 axis 理解成:
数组的某一个方向,或者某一个维度编号。
比如一个数组的形状是:
(2, 3)
这表示它有两个维度:
- 第 0 维大小是 2
- 第 1 维大小是 3
NumPy 就把这两个维度分别编号为:
axis=0axis=1
所以,axis 其实不是“行”或者“列”本身,它更像是在说:
“我要针对第几个维度来做操作。”
为什么不用 row 和 col
原因一:一维数组根本没有 row 和 col
比如:
a = numpy.array([10, 20, 30])
它的形状是:
(3,)
这是一个一维数组。
这时候你说它有“行”吗?不太准确。
你说它有“列”吗?也不准确。
但你可以说:
- 它只有一个轴
- 这个轴就是
axis=0
所以在一维数组里,axis=0 仍然是一个统一、自然的说法。
原因二:三维数组已经不止行和列了
比如一个三维数组:
a.shape = (2, 3, 4)
这表示它有 3 个维度。
这时候你再说:
- row
- col
就不够用了。
因为第三个方向叫什么?
你总不能继续发明:
- row
- col
- depth
那四维呢?五维呢?
名字会越来越乱。
而 NumPy 的做法很统一:
- 第一个方向:
axis=0 - 第二个方向:
axis=1 - 第三个方向:
axis=2 - 第四个方向:
axis=3
这样不管几维,都能描述。
这就是为什么数学和编程里更喜欢用“维度编号”而不是“行列”这种只适合二维的名字。
原因三:很多函数本来就不是“按行/按列”那么简单
比如 sum()、max()、mean()、argmax() 这些函数,都有 axis 参数。
如果 NumPy 写成:
sum(row=?)
sum(col=?)
那一维怎么办?三维怎么办?四维怎么办?
它根本不统一。
而用 axis 就很统一:
numpy.sum(a, axis=0)
numpy.sum(a, axis=1)
numpy.sum(a, axis=2)
无论数组几维,这套写法都成立。
所以你可以把 axis 看成 NumPy 的“统一语言”。
在二维数组里,为什么 axis=0 看起来像“行方向”?
这也是一个特别容易让人绕进去的地方。
先看一个二维数组:
a = numpy.array([
[1, 2, 3],
[4, 5, 6]
])
它的形状是:
(2, 3)
这表示:
- 第 0 维大小是 2,也就是有 2 行
- 第 1 维大小是 3,也就是有 3 列
所以这里:
axis=0对应的是“行这一维”axis=1对应的是“列这一维”
但是要注意:
“axis=0 是行这一维”
不等于
“axis=0 就是横着的一行”
它说的是“第 0 个维度”,不是说“第 0 行”。
这个区别很重要。
为什么有时候会觉得 axis=0 是“上下”,有时候又像是“按列”?
这是初学者最常见的困惑之一。
原因是:
axis 在不同函数里,表示的不是完全同一层直觉。
例如:
在 concatenate() 里
axis=0 表示沿着第 0 轴拼接。
对于二维数组来说,你会直观地感觉成:
上下拼接
因为行数增加了。
在 sum() 里
如果你写:
numpy.sum(a, axis=0)
你会发现结果像是在“按列求和”。
比如:
a = numpy.array([
[1, 2, 3],
[4, 5, 6]
])
print(numpy.sum(a, axis=0))
结果是:
[5 7 9]
这是把每一列加起来了。
于是很多人就懵了:
“不是说 axis=0 是行吗?为什么这里变成按列了?”
其实并不矛盾。
因为在 sum(axis=0) 里,意思是:
沿着第 0 轴去压缩、去合并。
第 0 轴是“行这一维”,你把“行这一维”压掉之后,剩下的自然就是每一列的结果。
所以:
- 在
concatenate(axis=0)中,表示沿第 0 维去扩展 - 在
sum(axis=0)中,表示沿第 0 维去汇总
函数动作不同,你看到的直观效果也不同。
但底层逻辑其实是一致的:
都是针对第 0 轴进行操作。
所以 axis 最准确的理解方式是什么
如果你想建立更稳的理解,不要死记:
axis=0= 行axis=1= 列
因为这个记法只在二维里部分好用,而且一到别的函数就容易混乱。
更稳的理解应该是:
axis 表示“第几个维度”
然后再结合函数去看:
- 是沿这个维度拼接
- 还是沿这个维度求和
- 还是沿这个维度找最大值
- 还是沿这个维度重排
这样理解会更通用。
一个类比:把数组想成一个盒子
你可以把数组想成一个有多个方向的盒子。
二维数组像一张表,有两个方向:
- 上下方向
- 左右方向
三维数组像很多张表叠起来,就有三个方向:
- 第一个方向
- 第二个方向
- 第三个方向
NumPy 不关心你把它叫“行”“列”“深度”还是别的名字。
它只关心:
- 第 0 个方向
- 第 1 个方向
- 第 2 个方向
这就像坐标轴一样:
- x 轴
- y 轴
- z 轴
你不会问“为什么不用左和右来命名 x 轴”,因为坐标轴本来就是统一抽象。
NumPy 的 axis 也是类似的思路。
你现阶段最该怎么记
对于初学阶段,我建议你分两层记忆。
第一层:做题时的直观记法
在二维数组里先记:
axis=0:和“上下”有关axis=1:和“左右”有关
这个记法最适合你现在做 concatenate()、sum()、reshape() 相关的基础题。
第二层:更本质的理解
同时再补上一个更底层的认识:
axis=0是第 0 个维度axis=1是第 1 个维度axis=2是第 2 个维度
这样以后你学到三维数组、图像数组、深度学习张量时,就不会卡住。
一张对比表:为什么不用 row/col
| 写法 | 适用范围 | 优点 | 缺点 |
|---|---|---|---|
row / col | 主要适合二维 | 直观 | 不能推广到一维、三维、更多维 |
axis=0 / axis=1 / axis=2 | 适合任意维数组 | 统一、通用、可扩展 | 初学时不如行列直观 |
所以不是 row/col 不好,而是它的适用范围太窄。
NumPy 作为一个处理通用多维数组的库,必须采用更通用的表达方式。
回到你最关心的一点:为什么 NumPy 要这样设计
因为 NumPy 不是“专门处理表格”的库,而是“处理多维数组”的库。
只要它要处理的是多维数组,就不能把接口设计死在“行和列”上。
所以它选择了更抽象、但也更强大的方式:
用 axis 表示维度编号。
这就是为什么你会看到:
axis=0
axis=1
axis=2
而不是:
row
col
本节小结
“为什么叫 axis=0、axis=1,而不是 row 或 col?”
最核心的答案就是一句话:
因为 row 和 col 只适合二维数组,而 NumPy 处理的是任意维度的数组,所以必须用更通用的 axis。
你现在可以这样记:
axis本质上是“第几个维度”- 二维里它可以暂时对应成“行方向 / 列方向”
- 但 NumPy 之所以不用
row/col,是为了适配一维、三维、更多维数组 - 所以
axis是一个更抽象,但更统一的设计
小练习
先不写代码,只思考下面这个问题:
a.shape = (2, 3, 4)
请你试着回答:
1. 这个数组一共有几个轴?
2. 分别是哪几个 axis?
3. 为什么这时候再用 row 和 col 就不够了?
提示:
- shape 里有几个数字,就有几个轴
- 轴从 0 开始编号,不是从 1 开始



