在标量上使用len的最pythonic方法是什么?

时间:2014-10-23 16:13:59

标签: python iterable typechecking

我读了这个问题

python: how to identify if a variable is an array or a scalar

但是当使用以下代码时,np.array会出现错误,如下所示。

import collections

isinstance(np.arange(10), collections.Sequence)
# returns false

我觉得有点烦人,我无法len(1)而只是1

我能想到的唯一工作是try except语句,如下所示:

a = 1
try:
    print len(a)
except TypeError:
    print 1

有更多的Pythonic方式吗?

3 个答案:

答案 0 :(得分:6)

collections.Sequence仅适用于序列对象,它是一种非常特定类型的可迭代对象。顺便提一下,numpy.ndarray(由numpy.arange返回)不是序列。

您需要测试collections.Iterable,它代表任何可迭代对象:

>>> isinstance([1, 2, 3], collections.Iterable)
True
>> isinstance(np.arange(10), collections.Iterable)
True
>>> isinstance(1, collections.Iterable)
False
>>>

collections.Sized,代表与len一起使用的任何对象:

>>> isinstance([1, 2, 3], collections.Sized)
True
>>> isinstance(np.arange(10), collections.Sized)
True
>>> isinstance(1, collections.Sized)
False
>>>

然后,您可以使用条件表达式或类似方法来执行您想要的操作:

print len(a) if isinstance(a, collections.Iterable) else 1

print len(a) if isinstance(a, collections.Sized) else 1

有关collections模块中可用抽象基类的完整列表,请参阅Python文档中的Collections Abstract Base Classes

答案 1 :(得分:4)

我只是提出另一个可能的选择:

length = getattr(obj, '__len__', lambda:1)()

因此,从对象获取__len__方法,或者始终返回1的函数,然后调用它以获得结果。

我不会说它是Pythonic,但是避免了导入和异常处理。但是,如果它是一个collections.Sized和一个条件语句,并且将它放在一个名为len_or_1的辅助函数中,我仍然可以进行比较。

答案 2 :(得分:0)

虽然这不是pythonic,因为它使用numpy是另一种巧妙的方法来使这项工作:

import numpy as np
a = 1
aSh = np.shape(a)
if len(aSh) == 0:
    print 1
else:
    print max(aSh)

它提供了一个应该与标量,列表和矩阵一起使用的行为。