[英]Python-numpy test for ndarray using ndim
我正在研究一个需要大量数值数组计算的Python项目。 不幸的是(或者幸运的是,取决于你的POV),我是Python的新手,但多年来一直在做MATLAB和Octave编程(APL之前)。 我习惯于将每个变量自动输入到矩阵浮点数,并且仍然习惯于检查输入类型。
在我的许多函数中,我要求输入S是numpy.ndarray
的大小(n,p)
,所以我必须测试该类型(S)是numpy.ndarray
并获取值(n,p) = numpy.shape(S)
。 一个潜在的问题是输入可能是list / tuple / int / etc ......,另一个问题是输入可能是shape ()
数组: S.ndim = 0
。 在我看来,我可以同时测试变量类型,修复S.ndim = 0
问题,然后得到我的维度:
# first simultaneously test for ndarray and get proper dimensions
try:
if (S.ndim == 0):
S = S.copy(); S.shape = (1,1);
# define dimensions p, and p2
(p,p2) = numpy.shape(S);
except AttributeError: # got here because input is not something array-like
raise AttributeError("blah blah blah");
虽然它有效,但我想知道这是否有效? ndim的文档字符串说
如果它还不是ndarray,则尝试转换。
我们肯定知道numpy可以轻松地将int / tuple / list转换为数组,所以我很困惑为什么会为这些类型的输入引发AttributeError,当numpy应该这样做
numpy.array(S).ndim;
这应该工作。
在为NumPy代码进行输入验证时,我总是使用np.asarray
:
>>> np.asarray(np.array([1,2,3]))
array([1, 2, 3])
>>> np.asarray([1,2,3])
array([1, 2, 3])
>>> np.asarray((1,2,3))
array([1, 2, 3])
>>> np.asarray(1)
array(1)
>>> np.asarray(1).shape
()
此功能具有很好的功能,它只在必要时复制数据; 如果输入已经是ndarray
,则数据保留在原位(只有类型可能会被更改,因为它也摆脱了那个讨厌的np.matrix
)。
ndim的文档字符串说
这是函数np.ndim
的文档字符串,而不是ndim
属性,非NumPy对象没有。 您可以使用该功能,但效果可能是数据可能被复制两次,因此请执行以下操作:
S = np.asarray(S)
(p, p2) = S.shape
如果S.ndim != 2
这将引发ValueError
。
[最后说明:你不需要;
在Python中,如果你只是遵循缩进规则。 实际上,Python程序员避开了分号。
鉴于对@larsmans回答的评论,您可以尝试:
if not isinstance(S, np.ndarray):
raise TypeError("Input not a ndarray")
if S.ndim == 0:
S = np.reshape(S, (1,1))
(p, p2) = S.shape
首先,明确检查S
是否是ndarray
的(子类)。 然后,如果需要,可以使用np.reshape
复制数据(当然np.reshape
重新整形)。 最后,你得到了维度。
请注意,在大多数情况下, np
函数将首先尝试访问ndarray
的相应方法,然后尝试将输入转换为ndarray
(有时将其保留为子类,如np.asanyarray
,有时不会(如np.asarray(...)
)。 np.asarray(...)
,使用方法而不是函数总是更有效:这就是我们使用S.shape
而不是np.shape(S)
。
另一点: np.asarray
, np.asanyarray
, np.atleast_1D
......都是更通用的函数np.array
。 例如, asarray
将array
的可选copy
参数设置为False
, asanyarray
设置相同并设置subok=True
, atleast_1D
设置ndmin=1
, atleast_2d
设置ndmin=2
... np.array
,使用np.array
总是更容易用适当的论据。 但正如一些评论中提到的那样,这是一种风格问题。 快捷方式通常可以提高可读性,这始终是一个需要牢记的目标。
在任何情况下,当你使用np.array(..., copy=True)
,你明确地要求提供初始数据的副本,有点像做一个list([....])
。 即使没有其他更改,您的数据也将被复制。 这有它的缺点的优势(如我们在法国的说),例如,你可以改变的order
从行第一C
到列第一F
。 但无论如何,你得到你想要的副本。
使用np.array(input, copy=False)
,始终会创建一个新数组。 如果后者已经是ndarray
(也就是说,不浪费内存),它将指向同一块内存作为input
,或者如果input
不是,则将“从头开始”创建一个新内存块。 有趣的情况当然是input
是一个ndarray
。
在函数中使用此新数组可能会也可能不会更改原始输入,具体取决于函数。 您必须检查要使用的函数的文档,以查看它是否返回副本。 NumPy开发人员努力限制不必要的副本(遵循Python示例),但有时无法避免。 文档应该明确说明发生了什么,如果没有或者不清楚,请提及。
如果出现问题, np.array(...)
可能会引发一些异常。 例如,尝试使用带有["STRING", 1]
类的输入的dtype=float
将引发ValueError
。 但是,我必须承认我不记得在所有情况下哪些例外,请相应地编辑这篇文章 。
欢迎来到堆栈溢出。 这归结为几乎一种风格选择,但我看到处理这种情况的最常见方式是将输入转换为数组。 Numpy为此提供了一些有用的工具。 numpy.asarray
已被提及,但这里还有一些。 numpy.at_least1d
类似于asarray
,但asarray
()数组为(1,) numpy.at_least2d
与上面相同,但重塑0d和1d数组为2d,即(3,)到(1,3)。 我们将“array_like”输入转换为数组的部分原因仅仅是因为我们很懒,例如有时写foo([1, 2, 3])
比foo(numpy.array([1, 2, 3]))
更容易foo(numpy.array([1, 2, 3]))
,但这也是numpy本身的设计选择。 请注意以下工作:
>>> numpy.mean([1., 2., 3.])
>>> 2.0
在numpy.mean
的文档中,我们可以看到x应该是“array_like”。
Parameters ---------- a : array_like Array containing numbers whose mean is desired. If `a` is not an array, a conversion is attempted.
话虽这么说,有些情况下你只想接受数组作为参数而不是所有“array_like”类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.