这是我的代码中经常发生的情况。假设我有一个函数do_sth(a,b)
,仅出于本示例的目的,只需a+b
使用a,b
一维numpy
数组或标量进行计算。在很多情况下,我需要函数来广播操作,这样如果两者a,b
都是一维数组,结果将是一个二维数组。我的意思的一个例子如下:
do_sth(1,2) -> 3
do_sth([1,2],0) -> array([1, 2])
do_sth(0,[3,4]) -> array([3, 4])
do_sth([1,2],[3,4]) -> array([[4, 5], [5, 6]])
这有点类似于 numpy 的ufunc
行为方式。一个可能的实现如下:
from numpy import newaxis, atleast_1d
def do_sth(a, b):
"a,b should be either 1d numpy arrays or scalars"
a, b = map(atleast_1d, [a, b])
# the line below mocks a more complicated calculation
res = a[:, newaxis] + b[newaxis]
conds = [a.size == 1, b.size == 1]
if all(conds):
return res[0, 0]
elif any(conds):
return res.ravel()
else:
return res
如您所见,有很多样板。第一个问题是:这是进行这种输入/输出转换的正确方法吗?有没有理由不使用装饰器来处理这种情况?有没有关于此事的指导方针?
此外,更复杂的计算,在这里被加法模拟,如果a
或者b
是具有 2D、3D 形状的 numpy 数组,通常会严重失败。从某种意义上说,计算失败的点并不明显,或者在代码的不同版本中可能会随时间变化,并且很难看出错误与错误输入形状之间的联系。我认为不建议将复杂的计算放在一个try/except
块中(遵循python EAFP)。在这种情况下,在函数开头检查 2 个数组的形状是否正确?有没有其他选择?是否有一个 numpy 函数允许同时将输入转换为 numpy 数组,并检查输入是否与一定数量的维度兼容,例如asarray_withdim(arr,ndim=5)
?