python:如何识别变量是数组还是标量


283

我有一个接受参数的函数NBins。我想用标量50或数组对此函数进行调用[0, 10, 20, 30]。我如何识别函数的长度NBins是多少?或换句话说,如果它是标量或向量?

我尝试了这个:

>>> N=[2,3,5]
>>> P = 5
>>> len(N)
3
>>> len(P)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()
>>> 

正如你看到的,我不能申请lenP,因为它不是一个数组....有什么样isarrayisscalar在Python?

谢谢


3
您是否尝试过测试type
Sukrit Kalra

Answers:


388
>>> isinstance([0, 10, 20, 30], list)
True
>>> isinstance(50, list)
False

要支持任何类型的序列,请选中collections.Sequence而不是list

注意isinstance还支持一个元组类,type(x) in (..., ...)应避免检查,这是不必要的。

您可能还想检查 not isinstance(x, (str, unicode))


3
谢谢,我没有想到list
倒数

3
尽管这是一个很好的答案,但collections.Sequence字符串的ABC也是这样,因此应考虑在内。我正在使用类似的东西if type(x) is not str and isinstance(x, collections.Sequence):。这不是很好,但是很可靠。
bbenne10

2
@ bbenne10当然可以,但要避免使用type,同时还要检查not isinstance(x, (str, unicode))Python 2
jamylak

为什么说“应避免并且不必要检查(...,...)中的type(x)”?如果您这样说,那将很好地解释为什么,也许我不是唯一想知道为什么应该避免使用它的人。
奥利维尔·庞斯


118

先前的答案假定该数组是python标准列表。作为经常使用numpy的人,我建议使用以下Python测试:

if hasattr(N, "__len__")

12
字符串具有__len__属性(因此,我想,从技术上讲,不是技术上的标量类型)
xofer14年

20
if hasattr(N, '__len__') and (not isinstance(N, str))将适当地考虑字符串。
Thucydides411 2014年

1
还要解释python 3上的字典
Bruno Henrique

44

将@jamylak和@ jpaddison3的答案结合在一起,如果您需要对作为输入的numpy数组保持鲁棒性,并以与列表相同的方式处理它们,则应使用

import numpy as np
isinstance(P, (list, tuple, np.ndarray))

对于list,tuple和numpy数组的子类,这是可靠的。

而且,如果您还想对序列的所有其他子类(不仅是列表和元组)具有鲁棒性,请使用

import collections
import numpy as np
isinstance(P, (collections.Sequence, np.ndarray))

为什么要用这种方法isinstance而不是type(P)与目标值进行比较?这是一个示例,我们制作并研究NewListlist的一个琐碎子类的行为。

>>> class NewList(list):
...     isThisAList = '???'
... 
>>> x = NewList([0,1])
>>> y = list([0,1])
>>> print x
[0, 1]
>>> print y
[0, 1]
>>> x==y
True
>>> type(x)
<class '__main__.NewList'>
>>> type(x) is list
False
>>> type(y) is list
True
>>> type(x).__name__
'NewList'
>>> isinstance(x, list)
True

尽管xy比较平等,通过处理它们type会导致不同的行为。然而,由于x是的子类的实例list,使用isinstance(x,list)得到所需的行为和治疗xy以相同的方式。


这是最适合我需要的答案。我也刚刚添加了设置。因为我不想对命令有足够的了解。isinstance(P, (list, tuple, set, np.ndarray))
圣地亚哥

32

numpy中有与isscalar()等效的东西吗?是。

>>> np.isscalar(3.1)
True
>>> np.isscalar([3.1])
False
>>> np.isscalar(False)
True

6
最好有一个例子:>>> np.isscalar('abcd')返回True
Syrtis Major

谢谢!这是一个比上述任何一个示例都更为通用的示例,应该优先使用。这也是对OP问题的直接回答。
瓦尔Sifón

1
真好 尽管一个棘手的问题是isscalar(None)返回False。Numpy将其实现为return (isinstance(num, generic) or type(num) in ScalarType or isinstance(num, numbers.Number))
Shital Shah,

5
不,可悲。numpy.isscalar()功能存在许多无法协调的设计缺陷,将来可能会不推荐使用。用官方文档来解释:“几乎在所有情况下np.ndim(x) == 0都应使用,而不是np.isscaler(x),因为对于0d数组,前者也将正确返回true。” 因此,一个健壮的,向前兼容的替代方案numpy.isscalar()将是琐碎的包装numpy.ndim():例如def is_scalar(obj): return np.ndim(obj) == 0
Cecil Curry,

实际上,不应np.isscalar混淆,这是令人困惑的。使用官方文档提示np.array.ndim无处不在,即np.isscalar(np.array(12))是假,而应该被视为标量,因为np.array(12).ndim是0
knh190

17

虽然@jamylak的方法更好,但这是另一种方法

>>> N=[2,3,5]
>>> P = 5
>>> type(P) in (tuple, list)
False
>>> type(N) in (tuple, list)
True

2
如果对答案不满意的人也给出了理由,那将是很棒的。
Sukrit Kalra

我实际上已经投票赞成,但是后来意识到它在2.7中不起作用:>>> p = [] >>> type(p)in(list)Traceback(last last call last):File“ <stdin>”第1行,在<模块>
奥列格Gryb

@OlegGryb:试试看type(p) in (list, )
Sukrit Kalra 2014年

啊,它是右边的一个元组,不是列表,知道了,谢谢,它现在可以使用了。很遗憾,我无法投票2次-迄今为止最好的解决方案:)
Oleg Gryb 2014年

3

另一种替代方法(使用类属性):

N = [2,3,5]
P = 5

type(N).__name__ == 'list'
True

type(P).__name__ == 'int'
True

type(N).__name__ in ('list', 'tuple')
True

无需导入任何东西。


3

这是我找到的最佳方法:检查__len__和的存在__getitem__

您可能会问为什么?原因包括:

  1. 该流行方法isinstance(obj, abc.Sequence)在某些对象(包括PyTorch的Tensor)上失败,因为它们未实现__contains__
  2. 不幸的是,Python的collections.abc中没有任何东西可以检查__len__并且__getitem__我认为这是处理类似数组对象的最小方法。
  3. 它适用于列表,元组,ndarray,Tensor等。

因此,事不宜迟:

def is_array_like(obj, string_is_array=False, tuple_is_array=True):
    result = hasattr(obj, "__len__") and hasattr(obj, '__getitem__') 
    if result and not string_is_array and isinstance(obj, (str, abc.ByteString)):
        result = False
    if result and not tuple_is_array and isinstance(obj, tuple):
        result = False
    return result

请注意,我添加了默认参数,因为大多数时候您可能希望将字符串视为值,而不是数组。元组也是如此。


2
>>> N=[2,3,5]
>>> P = 5
>>> type(P)==type(0)
True
>>> type([1,2])==type(N)
True
>>> type(P)==type([1,2])
False

2

您可以检查变量的数据类型。

N = [2,3,5]
P = 5
type(P)

它将以P的数据类型输出。

<type 'int'>

这样就可以区分它是整数还是数组。


2

令我惊讶的是,这样的基本问题似乎在python中没有即时的答案。在我看来,几乎所有建议的答案都使用某种类型检查,通常在python中不建议这样做,并且它们似乎仅限于特定情况(它们因使用不同的数字类型或非元组或列表的通用可迭代对象而失败)。

对我来说,更好的方法是导入numpy并使用array.size,例如:

>>> a=1
>>> np.array(a)
Out[1]: array(1)

>>> np.array(a).size
Out[2]: 1

>>> np.array([1,2]).size
Out[3]: 2

>>> np.array('125')
Out[4]: 1

另请注意:

>>> len(np.array([1,2]))

Out[5]: 2

但:

>>> len(np.array(a))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-40-f5055b93f729> in <module>()
----> 1 len(np.array(a))

TypeError: len() of unsized object

我也感到惊讶的是,它们似乎都不与发电机打交道。
RhysC

2

只需使用size代替len

>>> from numpy import size
>>> N = [2, 3, 5]
>>> size(N)
3
>>> N = array([2, 3, 5])
>>> size(N)
3
>>> P = 5
>>> size(P)
1

2
NameError:名字“尺寸”是没有定义

1
确实如此。我在使用numpy大小时没有注意到它。您需要:从numpy导入大小开始
Mathieu Villion

2
np.size(5)并且np.size([5])都是== 1,所以这不能正确地区分类型(即,确定标量),我认为这是目标。
迈克尔,

这是一个有趣的说法。原始问题涉及isscalar,这是Matlab函数。在Matlab中,标量和大小为1的数组之间绝对没有区别,可能是矢量还是N维数组。恕我直言,这是Matlab的优点。
Mathieu Villion

0

preds_test [0]的形状为(128,128,1),让我们使用isinstance()函数检查其数据类型isinstance接受2个参数。第一个参数是数据第二个参数是数据类型isinstance(preds_test [0],np.ndarray)给出Output为True。这意味着preds_test [0]是一个数组。


0

为了回答标题中的问题,判断变量是否为标量的直接方法是尝试将其转换为浮点数。如果得到TypeError,则不是。

N = [1, 2, 3]
try:
    float(N)
except TypeError:
    print('it is not a scalar')
else:
    print('it is a scalar')
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.