Python数据分析与处理(三):深入理解 NumPy的np.size()与np.shape()
本文详细讲解了NumPy中shape和size的核心概念与使用技巧。shape返回数组维度结构(如(3,4)),size返回元素总数。文章对比了属性访问(arr.shape/size)和函数调用(np.shape/size)的差异,分析了0-D数组、不规则列表等特殊情况下的处理建议,并提供了常见场景的推荐写法。强调优先使用属性访问以提高性能,同时注意边界情况处理,最后给出了参数校验等实用示例,帮助
文章目录
前言
在使用 NumPy 进行数组与数值计算时,了解数组的形状(shape)和元素个数(size)是非常基础且重要的技能。很多初学者常把 np.size() 与 np.shape() 混淆,或在边界情况下(例如 0-D、非规则列表、或 object 数组)出现错误判断。本文将详细讲解两者的含义、函数与属性的用法、常见陷阱以及实用建议,并配上可直接运行的代码示例与小工具函数,便于测试与使用。
一、核心概念
shape(或np.shape(x))返回形状元组,描述每一轴(axis)的长度,例如(3, 4)。它表示数组的维度结构。size(或np.size(x))返回数组中元素的总数(所有轴长度的乘积),例如12。np.size还支持axis参数用于查询某一轴的长度。
二、API 速查表及实例
-
arr.shape—— ndarray 属性,返回 tuple(例如(m, n))。推荐首选。 -
np.shape(arr)—— 函数,接受任意 array-like,返回形状 tuple。对非规则嵌套序列的行为依赖于np.array的转换结果。 -
arr.size—— ndarray 属性,返回元素总数(int)。推荐首选。 -
np.size(arr, axis=None)—— 函数,返回元素总数或指定轴的长度。返回 int。 -
简单示例
import numpy as np
# 创建 3x4 数组
a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print('shape:', a.shape) # (3, 4)
print('np.shape:', np.shape(a)) # (3, 4)
print('size:', a.size) # 12
print('np.size:', np.size(a)) # 12
print('np.size(axis=0):', np.size(a, axis=0)) # 3
print('np.size(axis=1):', np.size(a, axis=1)) # 4
print('ndim:', a.ndim) # 2
print('len(a):', len(a)) # 3 (等同于 shape[0])
三、特殊情况与常见陷阱
1. 0-D(标量)数组
b = np.array(5) # 0-D
print(b.shape) # ()
print(b.size) # 1
# 注意:b.shape[0] 会报错,因为 shape 是空 tuple
处理建议:在访问 shape[0] 之前,先检查 arr.ndim 或使用 len(arr) 仅在确实是至少 1-D 时使用。
2. 不规则(ragged)嵌套列表
c = [ [1, 2], [3, 4, 5] ]
arr = np.array(c)
print(arr) # array([list([1, 2]), list([3, 4, 5])], dtype=object)
print(arr.shape) # (2,) —— 变成了 1-D 的 object 数组
说明:对不规则嵌套列表,np.array 会生成 dtype=object 的一维数组,此时 shape 不反映内部每个子列表长度, 使用 np.shape(c)(直接对 Python list 调用)会根据 Python 对象的序列规则返回 (2,)。小心不要误以为得到 (2, 3)。
3. 使用 shape[0] 的风险
当数组可能是 0-D 时,直接用 shape[0] 会抛出 IndexError。防护写法:
if arr.ndim >= 1:
n_rows = arr.shape[0]
else:
n_rows = 1 # 或者按需处理标量情况
4. len(arr) 的含义
len(arr) 返回最外层轴(axis 0)的长度,如果是 0-D(标量)数组会报 TypeError。因此 len 只在你确定数组至少是 1-D 时安全使用。
四、性能与使用建议
- 优先使用属性访问:对于 ndarray,使用
arr.shape/arr.size比np.shape(arr)/np.size(arr)更直接且速度更快(属性访问避免函数调用开销)。 - 明确意图:如果目的是获取“元素总数”,用
arr.size;若目的是“某轴长度”,用arr.shape[axis]。代码可读性更好,也更不易出错。 - 对外部/任意 array-like 使用
np.shape:当你接受任意 sequence(list/tuple/array-like)作为输入并需要安全获取形状信息,np.shape(obj)是通用的。但请谨慎处理 ragged 情况。
五、常见场景 & 推荐写法
场景 1:验证数组是否为空
# 判空:没有元素
if arr.size == 0:
# 处理空数组
pass
场景 2:检查是否是向量或矩阵
if arr.ndim == 1:
# 向量
elif arr.ndim == 2:
# 矩阵
场景 3:按行/列循环
# 按行遍历(确保至少 2-D 或 1-D)
for i in range(arr.shape[0]):
row = arr[i]
# 或更 Pythonic:
for row in arr:
...
场景 4:需要某轴长度但不确定 ndim
def axis_length(arr, axis=0):
arr = np.asarray(arr)
if axis < 0:
axis = arr.ndim + axis
if axis < 0 or axis >= arr.ndim:
raise IndexError('axis out of range')
return arr.shape[axis]
六、常用语句
arr.shape—— 元组,例如(m, n)。arr.size—— 元素总数(int)。len(arr)—— 等同于arr.shape[0](前提:arr.ndim >= 1)。np.shape(obj)—— 通用函数,适用于 array-like。对 ragged 列表会返回(n,)。注意dtype=object。np.size(obj, axis=k)—— 返回 axis k 的长度或总元素数。
七、实战示例
用 shape 和 size 做参数校验
import numpy as np
def validate_inputs(X, y=None):
X = np.asarray(X)
if X.ndim != 2:
raise ValueError('X must be 2-D (n_samples, n_features)')
if y is not None:
y = np.asarray(y)
if y.size != X.shape[0]:
raise ValueError('y must have same number of samples as X')
return X, y
上面示例展示了:用 shape 做结构检查,用 size 做元素计数比较,两者结合能写出稳健的输入校验逻辑。
总结
shape给出数组的结构(每轴长度),size给出数组的元素数量(所有轴长度的乘积)。二者是不同维度的信息,但常一起使用以编写健壮的数值代码。- 推荐风格:对 ndarray 使用
arr.shape/arr.size(优于np.shape/np.size);当接口接受任意 array-like 时,可用np.asarray+ 属性访问以标准化输入。对 0-D、非规则嵌套列表(ragged)等边界情况要显式处理,避免直接索引shape[0]或盲目使用len。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)