NumPy轴参数axis详解:从聚合到拼接,彻底掌握多维数组操作
1. 从一次令人困惑的报错说起最近在调试一个图像处理相关的脚本时遇到了一个典型的numpy报错ValueError: unexpected numpy array shape (96, 64, 16)。这个错误本身指向数组形状不匹配但更深层的原因是我在调用某个库函数时错误地理解了axis参数的含义把本应沿着高度方向axis0的操作用在了通道方向axis2上。这让我意识到即便是在numpy这种基础库上axis这个看似简单的概念依然是很多朋友从“会用”到“用好”的一道坎。你可能已经熟练使用np.sum()、np.mean()但当面对一个三维数组或者需要组合使用np.concatenate、np.stack时心里还是会嘀咕一下这个axis到底该填 0 还是 1今天我们就抛开那些抽象的数学定义用最直观的“数据视角”和大量的实操例子把axis0, 1, 2彻底讲透。无论你是正在用numpy做数据分析、机器学习还是科学计算理解axis都将让你对数组操作拥有更强的掌控力避免像我一样踩进形状不匹配的坑里。2. 重塑认知把“轴”想象成“括号层”很多教程一上来就画坐标轴说axis0是行axis1是列。这对于二维数组矩阵没问题但一旦升到三维或更高维这种说法就容易让人混乱。我更喜欢一种更普适的理解方式把axis理解为数组索引时中括号[]的层级。想象一下我们有一个三维数组arr_3d它的形状是(2, 3, 4)。在内存中数据是线性存储的但我们可以通过三层索引来访问任何一个元素arr_3d[i, j, k]。axis0对应的是最外层的中括号也就是第一个索引i的变化方向。当你固定j和k让i从 0 变到 1你是在“最外层”的单元之间移动。这个“最外层”的单元本身就是一个形状为(3, 4)的二维数组。axis1对应的是中间层的中括号即第二个索引j的变化方向。此时你固定了i选定了某个二维数组和k让j变化你是在这个二维数组的“行”之间移动。axis2对应的是最内层的中括号即第三个索引k的变化方向。固定了i和j选定了某一行让k变化你是在这一行的各个“列”或“元素”之间移动。这种“括号层”的理解方式可以无缝推广到 N 维数组axisn就对应第n1层中括号因为索引从0开始。让我们用一个具体的(2, 3, 4)数组来可视化import numpy as np # 创建一个形状为 (2, 3, 4) 的三维数组内容为 0~23 arr_3d np.arange(24).reshape(2, 3, 4) print(三维数组 arr_3d:) print(arr_3d) print(f形状: {arr_3d.shape}\n) # 打印第一个二维切片axis0 的第一个元素 print(arr_3d[0, :, :] (即 axis0 方向上的第一个元素):) print(arr_3d[0]) print(f形状: {arr_3d[0].shape}\n) # 打印第一个二维切片的第一行在 arr_3d[0] 这个二维数组里取 axis1 的第一个元素 print(arr_3d[0, 0, :] (即 arr_3d[0] 中 axis1 方向上的第一个元素):) print(arr_3d[0, 0]) print(f形状: {arr_3d[0, 0].shape}\n)输出会清晰地展示这种层级关系。记住这个核心比喻axis的值决定了你在哪一层括号上进行操作或“折叠”。接下来所有的聚合、拼接操作都是基于这个逻辑。3. 聚合操作沿着哪个轴“压扁”数据聚合函数如np.sum,np.mean,np.max,np.min等是axis参数最常用的场景。它的规则很明确指定axisn函数就会沿着这个轴的方向进行计算并且最终结果中这个轴的维度会消失被聚合掉。3.1 二维数组上的直观演示我们先从熟悉的二维数组开始建立一个牢固的直觉。arr_2d np.array([[1, 2, 3], [4, 5, 6]]) print(原始二维数组:) print(arr_2d) print(f形状: {arr_2d.shape}\n) # axis0: 沿着最外层行方向聚合行维度消失结果是一个长度为列数的一维数组。 sum_axis0 np.sum(arr_2d, axis0) print(np.sum(arr_2d, axis0):) print(sum_axis0) print(f结果形状: {sum_axis0.shape} - 原始形状 (2,3) 中的 2行被聚合掉了\n) # 计算过程 [14, 25, 36] [5, 7, 9] # axis1: 沿着中间层列方向聚合列维度消失结果是一个长度为行数的一维数组。 sum_axis1 np.sum(arr_2d, axis1) print(np.sum(arr_2d, axis1):) print(sum_axis1) print(f结果形状: {sum_axis1.shape} - 原始形状 (2,3) 中的 3列被聚合掉了\n) # 计算过程 [123, 456] [6, 15]实操心得对于二维数组一个快速记忆法是“axis0 跨行竖着加结果变横条axis1 跨列横着加结果变竖条”。你可以想象一根钉子axis就是钉子的方向钉子穿过的那些元素被加在了一起钉子方向对应的维度就没了。3.2 三维数组的深入剖析现在进入核心看三维数组。假设arr_3d形状为(2, 3, 4)我们可以把它想象成 2 张表格每张表格有 3 行 4 列。arr_3d np.arange(24).reshape(2, 3, 4) print(原始三维数组 (2, 3, 4):) print(arr_3d) print(f形状: {arr_3d.shape}\n) # axis0: 沿着“表格”本身的方向聚合。2张表格对应位置元素相加得到1张 (3,4) 的表格。 sum_axis0 np.sum(arr_3d, axis0) print(np.sum(arr_3d, axis0):) print(sum_axis0) print(f结果形状: {sum_axis0.shape} - (2,3,4) 中的 2 被聚合掉了\n) # 计算逻辑arr_3d[0, :, :] arr_3d[1, :, :] # axis1: 在每张表格内部沿着“行”的方向聚合。每张表的3行数据“压扁”成1行结果得到2张 (1,4) 的表格但 numpy 会默认去掉大小为1的维度所以显示为 (2,4)。 sum_axis1 np.sum(arr_3d, axis1) print(np.sum(arr_3d, axis1):) print(sum_axis1) print(f结果形状: {sum_axis1.shape} - (2,3,4) 中的 3 被聚合掉了\n) # 计算逻辑对 arr_3d[i, :, :] 在行方向求和i 从0到1。 # axis2: 在每张表格内部沿着“列”的方向聚合。每张表的每行数据“压扁”成1个数结果得到2张 (3,1) 的表格同样去掉大小为1的维度后为 (2,3)。 sum_axis2 np.sum(arr_3d, axis2) print(np.sum(arr_3d, axis2):) print(sum_axis2) print(f结果形状: {sum_axis2.shape} - (2,3,4) 中的 4 被聚合掉了\n) # 计算逻辑对 arr_3d[i, j, :] 在列方向求和i 从0到1j 从0到2。为了更直观我们可以用keepdimsTrue参数来保留被聚合的维度大小为1这在进行后续广播操作时非常有用。sum_axis1_keep np.sum(arr_3d, axis1, keepdimsTrue) print(np.sum(arr_3d, axis1, keepdimsTrue):) print(sum_axis1_keep) print(f结果形状: {sum_axis1_keep.shape}\n) # 此时形状为 (2, 1, 4)明确保留了“行”这个维度被聚合后的痕迹。3.3 高维数组的通用法则与形状推导对于任意维度的数组arr其形状为(d0, d1, d2, ..., dn)。 执行np.sum(arr, axisk)后结果的形状推导公式为新形状 (d0, d1, ..., d_{k-1}, d_{k1}, ..., dn)即直接去掉原形状中第k个位置的数字d_k。例如一个四维数组(a, b, c, d)axis0求和后形状为(b, c, d)axis1求和后形状为(a, c, d)axis2求和后形状为(a, b, d)axis3求和后形状为(a, b, c)这个法则对于所有聚合函数都适用。避坑指南当你对聚合结果形状感到不确定时不要猜直接打印.shape属性。这是最可靠的方法。同时理解keepdims的用途当你需要将聚合结果如每行的均值与原数组进行广播运算如减去均值时keepdimsTrue能保证维度对齐避免很多形状错误。4. 拼接与堆叠沿着哪个轴“插入”新数据另一大类频繁使用axis参数的函数是数组组合操作如np.concatenate,np.stack,np.vstack,np.hstack等。这里的逻辑与聚合稍有不同不是“压扁”而是“插入”或“扩展”。4.1np.concatenate在现有维度上连接np.concatenate要求所有输入数组在除拼接轴axis之外的维度上形状必须完全相同。它是在现有维度上直接延长。# 准备两个形状相同的二维数组 a np.array([[1, 2, 3], [4, 5, 6]]) b np.array([[7, 8, 9], [10, 11, 12]]) print(数组 a:) print(a) print(数组 b:) print(b) # axis0: 沿着行方向最外层拼接。要求列数相同。 cat_axis0 np.concatenate([a, b], axis0) print(\nnp.concatenate([a, b], axis0):) print(cat_axis0) print(f形状: {cat_axis0.shape} - 行数相加 (224)列数不变 (3)\n) # axis1: 沿着列方向内层拼接。要求行数相同。 cat_axis1 np.concatenate([a, b], axis1) print(np.concatenate([a, b], axis1):) print(cat_axis1) print(f形状: {cat_axis1.shape} - 列数相加 (336)行数不变 (2)\n)对于三维数组原理一致。假设我们有两个形状为(2, 3, 4)的数组block1和block2。axis0拼接得到(4, 3, 4)。可以理解为把两个“数据块”上下堆叠起来块数增加了。axis1拼接得到(2, 6, 4)。在每个数据块内部沿着行方向拼接行数增加了。axis2拼接得到(2, 3, 8)。在每个数据块内部的每一行沿着列方向拼接列数增加了。核心要点concatenate时axis指定了“哪个维度的尺寸会增加”。其他维度的尺寸必须严格相等。4.2np.stack创建新维度进行堆叠np.stack与concatenate的关键区别在于stack会创建一个新的维度而所有输入数组在所有现有维度上的形状必须完全相同。a np.array([1, 2, 3]) b np.array([4, 5, 6]) print(fa 形状: {a.shape}, b 形状: {b.shape}) # axis0: 在新的最外层维度上堆叠。结果形状为 (2, 3) stack_axis0 np.stack([a, b], axis0) print(f\nnp.stack([a, b], axis0) 形状: {stack_axis0.shape}) print(stack_axis0) # 相当于 np.array([a, b]) # axis1: 在新的中间维度上堆叠。结果形状为 (3, 2) stack_axis1 np.stack([a, b], axis1) print(f\nnp.stack([a, b], axis1) 形状: {stack_axis1.shape}) print(stack_axis1) # 相当于将 a 和 b 作为列向量并排放在一起stack的axis参数决定了新维度插入的位置。对于一堆形状为(d1, d2, ..., dn)的数组使用np.stack(arrays, axisk)后结果的形状变为(d1, d2, ..., d_k, len(arrays), d_{k1}, ..., dn)其中len(arrays)就是新插入的维度大小。4.3vstack与hstack的axis等价关系np.vstack垂直堆叠和np.hstack水平堆叠是concatenate在二维情况下的特化版理解它们与axis的对应关系有助于记忆。np.vstack([a, b])等价于np.concatenate([a, b], axis0)。垂直堆叠就是沿着行第0轴拼接。np.hstack([a, b])等价于np.concatenate([a, b], axis1)。水平堆叠就是沿着列第1轴拼接。对于一维数组vstack会先将其变为二维行向量再操作而hstack就是直接拼接。经验之谈在代码中我倾向于直接使用concatenate并明确指定axis因为它的语义最清晰且适用于任意维度。vstack/hstack在处理一维数组时容易产生意想不到的形状变化对新手不友好。明确axis的值是写出维度安全代码的关键。5. 实战场景与疑难排错理解了基本原理我们来看几个实战场景以及如何排查因axis使用不当引发的错误。5.1 场景一图像数据批处理中的均值归一化在计算机视觉中我们常有一个四维数组表示一批图像(batch_size, height, width, channels)。例如(32, 224, 224, 3)表示 32 张 224x224 的 RGB 图片。现在需要计算这批图片每个通道R, G, B的均值用于归一化。# 模拟一批图像数据 batch_images np.random.randn(32, 224, 224, 3).astype(np.float32) * 0.1 0.5 # 均值为0.5标准差为0.1 # 目标是计算每个通道的均值得到一个形状为 (3,) 的数组 # 错误做法沿着 axis0 (batch) 求均值不对这样会得到 (224,224,3)是每张图每个位置的平均。 mean_wrong np.mean(batch_images, axis0) print(f沿着 axis0 求均值的形状: {mean_wrong.shape}) # (224, 224, 3) # 正确做法我们需要聚合掉 batch, height, width 三个维度只保留 channel。 # 因此需要同时指定 axis(0, 1, 2) mean_correct np.mean(batch_images, axis(0, 1, 2)) print(f沿着 axis(0,1,2) 求均值的形状: {mean_correct.shape}) # (3,) print(f通道均值近似为: {mean_correct})这里的关键是axis参数可以接受一个元组指定多个轴同时进行聚合。这比连续调用多次np.mean更高效、更清晰。5.2 场景二多维数组的展平与axis的关系arr.flatten()或arr.ravel()会将数组展平成一维这个过程不涉及axis参数。但有时我们需要按特定顺序展平或者进行反向操作reshape这时就需要对轴顺序有深刻理解。numpy默认使用‘C’ 风格行优先的内存顺序。这意味着在展平或重塑时最右边的索引axis-1变化最快。对于形状为(2, 3, 4)的数组arrarr.flatten()得到的顺序相当于[arr[0,0,0], arr[0,0,1], arr[0,0,2], arr[0,0,3], arr[0,1,0], ..., arr[1,2,3]]你可以看到axis2列索引变化最快其次是axis1行索引最后是axis0块索引。当你使用reshape时新的形状必须与这个内在的线性顺序兼容。理解这个顺序有助于你正确地将一个聚合或切片后的结果重塑成想要的维度。5.3 疑难排错axis错误导致的典型报错最常见的错误就是shape mismatch形状不匹配和axis out of bounds轴越界。错误1axis索引越界arr_2d np.ones((3, 4)) try: result np.sum(arr_2d, axis2) # 二维数组只有 axis0 和 axis1 except np.AxisError as e: print(fAxisError: {e})对于一个ndim维的数组有效的axis取值范围是-ndim axis ndim。axis2对于二维数组是无效的。可以使用axis-1来指代最后一个轴对于二维数组就是axis1这在写通用函数时很常用。错误2拼接时非axis维度不匹配a np.ones((2, 3, 4)) b np.ones((2, 5, 4)) # 第二个维度行不同 try: c np.concatenate([a, b], axis1) # 想沿着行拼接但第三维列都是4看似可以 except ValueError as e: print(fValueError: {e}) # 实际报错所有输入数组的维数必须相同但索引0处的数组的维数为3索引1处的数组的维数为... 等等这里检查的是所有维度。 # 更准确的例子 a2 np.ones((2, 3, 4)) b2 np.ones((2, 3, 5)) # 第三维列不同 try: c2 np.concatenate([a2, b2], axis0) # 沿着 axis0 拼接要求其他维度 (1,2) 相同即 (3,4) 和 (3,5) 不同所以会报错。 except ValueError as e: print(fValueError: {e}) # 会报错维度不匹配concatenate要求所有非拼接轴对应的维度大小必须严格一致。在调试时要仔细核对每个输入数组的.shape属性。错误3对axis理解偏差导致的计算逻辑错误这是最隐蔽的错误代码不报错但结果不对。就像开篇提到的(96, 64, 16)形状问题。假设这是一个(batch, sequence, feature)的序列数据你想对每个序列sequence求均值应该用axis1。如果你错误地用了axis2就变成了对每个特征feature求均值完全改变了语义。这种错误只能通过仔细审查代码逻辑和对数据的理解来避免。排查心法遇到形状相关的错误第一反应是打印出操作前后所有关键变量的.shape。在脑子里或纸上画一下数据的维度图明确每个轴代表的物理意义如批次、高、宽、通道、序列长度、特征维度等。axis参数永远服务于你的业务逻辑你想消除或合并哪个物理维度就指定对应的轴。6. 更高维度的推广与axis参数的灵活应用对于四维、五维甚至更高维的数组常见于深度学习中的张量axis的概念完全一样只是索引层级更多了。你可以始终用“括号层”模型来理解。例如一个形状为(N, C, H, W)的卷积神经网络特征图分别代表批大小、通道数、高度、宽度axis0对应N在批次间操作。axis1对应C在通道间操作。axis2对应H在高度方向操作。axis3对应W在宽度方向操作。numpy的许多函数都支持axis参数其核心思想一致np.expand_dims(arr, axis): 在指定axis位置插入一个大小为1的新维度。np.expand_dims(arr, axis0)就是在最前面加一维。np.swapaxes(arr, axis1, axis2): 交换两个轴的位置。这在需要调整数据布局以适配不同库的API时非常有用例如(H,W,C)和(C,H,W)的转换。np.moveaxis(arr, source, destination): 将源轴移动到目标位置更通用的轴重排操作。np.apply_along_axis(func1d, axis, arr): 沿着指定轴将一维函数func1d应用于数组的每一个一维切片上。掌握axis的核心在于你不再把数组看成是黑盒而是能清晰地洞察其多维结构并精准地指挥numpy在这个结构的特定方向上执行操作。这需要练习但一旦掌握你对多维数据的处理能力将大幅提升。下次再面对一个多维数组时先别急着写代码花几秒钟想清楚每个轴的意义以及你希望操作沿着哪个方向进行这能节省大量的调试时间。

相关新闻

Elasticsearch模糊查询实战:从Wildcard陷阱到高性能方案设计

Elasticsearch模糊查询实战:从Wildcard陷阱到高性能方案设计

1. 从“LIKE”到“Wildcard”:理解ES模糊查询的本质在数据库的世界里,LIKE查询几乎是每个开发者入门时就会接触到的老朋友。无论是%keyword%还是_keyword_,它都能帮我们轻松搞定那些“记不全但记得一部分”的搜索需求。然而,当你踏…

2026/7/30 8:09:23 阅读更多 →
ADB命令实战:Android系统音量自动化控制与调试指南

ADB命令实战:Android系统音量自动化控制与调试指南

1. 项目概述:为什么ADB是调试音量的利器在Android应用开发或者日常的设备调试中,音量控制是一个看似基础却经常需要精细操作的功能。你可能遇到过这样的场景:正在测试一个音频播放应用,需要反复调整媒体音量来验证不同级别下的播放…

2026/7/30 8:09:23 阅读更多 →
AD2s1205旋变解码芯片实战:从硬件设计到软件配置全解析

AD2s1205旋变解码芯片实战:从硬件设计到软件配置全解析

1. 项目缘起:为什么我要啃AD2s1205这颗“硬骨头”?最近在搞一个伺服驱动器的项目,里面用到了旋转变压器(Resolver,简称旋变)作为电机位置传感器。选型的时候,硬件同事直接拍板用了ADI的AD2s1205…

2026/7/30 8:09:23 阅读更多 →

最新新闻

计算机毕业设计之Java物品租赁系统的设计与实现

计算机毕业设计之Java物品租赁系统的设计与实现

随着新经济的需求和新技术的发展,特别是网络技术的发展,如果可以建立起物品租赁系统,可以改变传统线下管理方式,在过去的时代里都使用传统的方式实行,既花费了时间,又浪费了精力。在信息如此发达的今天&…

2026/7/30 9:38:52 阅读更多 →
p051基于协同过滤的动漫推荐系统设计与实现_hive31(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_

p051基于协同过滤的动漫推荐系统设计与实现_hive31(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_

p051基于协同过滤的动漫推荐系统设计与实现_hive31(设计源文件万字报告讲解)(支持资料、图片参考_相关定制)_ python3.7djangohivespidermysql5.7vue 当人们打开系统的网址后,首先看到的就是首页界面。在这里,人们能够看到系统的导…

2026/7/30 9:38:52 阅读更多 →
从欧姆定律到工程实践:检流电阻与运放搭建高精度电流检测电路全解析

从欧姆定律到工程实践:检流电阻与运放搭建高精度电流检测电路全解析

1. 项目概述:从“检流电阻”到精准电流测量 在电路设计和调试中,电流测量是个绕不开的基础活。无论是评估一个电源模块的效率,还是监控电机的工作状态,亦或是保护电路免受过流损害,我们都需要知道“流过的电流到底有多…

2026/7/30 9:38:52 阅读更多 →
从C语言视角解析CPython整数对象实现原理与内存管理

从C语言视角解析CPython整数对象实现原理与内存管理

1. 项目概述:从C语言视角切入CPython源码如果你和我一样,对Python的运行机制充满好奇,不止步于“知其然”,更想“知其所以然”,那么直接阅读CPython的源码无疑是最佳路径。但面对数百万行代码,从哪里开始&a…

2026/7/30 9:38:52 阅读更多 →
开放量子系统:从Lindblad方程到量子退相干控制

开放量子系统:从Lindblad方程到量子退相干控制

开放量子系统(Open Quantum Systems)完整解析:从基础理论到实际应用 在量子计算和量子信息科学快速发展的今天,开放量子系统理论已成为理解和设计实际量子器件的核心基础。无论是量子计算机中的退相干问题,还是量子传感…

2026/7/30 9:38:52 阅读更多 →
网盘直链下载助手:技术原理与多平台应用深度解析

网盘直链下载助手:技术原理与多平台应用深度解析

网盘直链下载助手:技术原理与多平台应用深度解析 【免费下载链接】baiduyun 油猴脚本 - 一个免费开源的网盘下载助手 项目地址: https://gitcode.com/gh_mirrors/ba/baiduyun 在云存储服务普及的今天,用户面临着下载速度限制和跨平台兼容性的双重…

2026/7/30 9:37:51 阅读更多 →

日新闻

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:13 阅读更多 →
如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否曾经在浏览…

2026/7/30 0:00:13 阅读更多 →
“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

更多请点击: https://intelliparadigm.com 第一章:AI 教师备课辅助 AI 教师备课辅助系统正逐步成为教育数字化转型的核心支撑工具,它并非替代教师,而是通过语义理解、知识图谱与多模态生成能力,将教师从重复性劳动中解…

2026/7/30 0:00:13 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/29 22:18:20 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻