Python:检查对象是否是序列

时间:2010-05-30 00:43:25

标签: python if-statement sequence sequences

在python中有一种简单的方法来判断某些东西是不是序列吗?我试着这样做: if x is not sequence但是python不喜欢那个

8 个答案:

答案 0 :(得分:65)

iter(x)如果TypeError无法迭代,则会引发x - 但检查“接受”集合和词典,但它“拒绝”其他非序列,例如{ {1}}和数字。

另一方面,字符串(大多数应用程序想要考虑“单项”而非序列)实际上是序列(因此,除非特殊的字符串,否则任何测试都将确认他们是)。因此,这种简单的检查往往是不够的。

在Python 2.6及更高版本中,引入了抽象基类,并且在其他强大的功能中,它们为这种“类别检查”提供了更好的系统支持。

None

你会注意到字符串仍然被认为是“一个序列”(因为它们),但至少你得到了dicts并且设置不了。如果你想从你的“序列”的概念中排除字符串,你可以使用>>> import collections >>> isinstance([], collections.Sequence) True >>> isinstance((), collections.Sequence) True >>> isinstance(23, collections.Sequence) False >>> isinstance('foo', collections.Sequence) True >>> isinstance({}, collections.Sequence) False >>> isinstance(set(), collections.Sequence) False (但这也排除了元组,像字符串一样,是序列,但不是可变的),或明确地做:< / p>

collections.MutableSequence

品尝季节,热腾腾! - )

答案 1 :(得分:9)

我认为以下代码段可以满足您的需求:

def is_sequence(obj):
    return hasattr(type(obj), '__iter__')

答案 2 :(得分:6)

因为Python&#34;坚持&#34;鸭子打字,其中一种方法是检查对象是否有某个成员(方法)。

序列具有长度,具有项目序列,并支持切片[doc]。所以,它会是这样的:

def is_sequence(obj):
    t = type(obj)
    return hasattr(t, '__len__') and hasattr(t, '__getitem__')
    # additionally: and hasattr(t, '__setitem__') and hasattr(t, '__delitem__')

它们都是特殊方法,__len__()应该返回项目数,__getitem__(i)应该返回一个项目(按顺序它是 i - 项目,但是没有映射),__getitem__(slice(start, stop, step))应该返回子序列,__setitem____delitem__就像您期望的那样。这是一个这样的契约,但对象是否真的这样做取决于对象是否遵守合同。

注意,上面的函数也会返回True进行映射,例如: dict,因为映射也有这些方法。要解决此问题,您可以执行更重的工作:

def is_sequence(obj):
    try:
        len(obj)
        obj[0:0]
        return True
    except TypeError:
        return False

但是大部分时间你都不需要这样做,只需做你想做的事情就像对象是一个序列一样,如果你愿意的话就抓住一个例外。这更像是pythonic。

答案 3 :(得分:5)

Python 2.6.5 documentation描述了以下序列类型:string,Unicode string,list,tuple,buffer和xrange。

def isSequence(obj):
    return type(obj) in [str, unicode, list, tuple, buffer, xrange]

答案 4 :(得分:1)

为了完整性。 numpy库中有一个实用程序is_sequence(“使用Python进行科学计算的基本软件包”)。

>>> from numpy.distutils.misc_util import is_sequence
>>> is_sequence((2,3,4))
True
>>> is_sequence(45.9)
False

但是它接受 sets 作为序列,并拒绝 strings

>>> is_sequence(set((1,2)))
True
>>> is_sequence("abc")
False

代码看起来有点像@adrian的代码(请参见numpy git code),有点不稳定。

def is_sequence(seq):
    if is_string(seq):
        return False
    try:
        len(seq)
    except Exception:
        return False
    return True

答案 5 :(得分:0)

你为什么要这样做?这里的常规方法是需要某种类型的东西(序列或数字或类似文件的对象等)然后使用它而不检查任何东西。在Python中,我们通常不使用类来承载语义信息,而只是使用定义的方法(这称为“鸭子打字”)。我们也更喜欢API,我们确切地知道会发生什么;如果要更改函数的工作方式,请使用关键字参数,预处理或定义另一个函数。

答案 6 :(得分:0)

对于Python 3和2.6+,您可以检查它是否为collections.Sequence的子类:

>>> import collections
>>> isinstance(myObject, collections.Sequence)
True

在Python 3.7中,您必须使用collections.abc.Sequencecollections.Sequence在Python 3.8中将被删除):

>>> import collections.abc
>>> isinstance(myObject, collections.abc.Sequence)
True

但是,这对于实现__len__()__getitem__()但不(应该)子类collections.Sequence的鸭子型序列不起作用。但它适用于所有内置的Python序列类型:列表,元组,字符串等。

虽然所有序列都是可迭代的,但并非所有可迭代的都是序列(例如,集合和字典是可迭代的,但不是序列)。选中hasattr(type(obj), '__iter__')将返回True的字典和集合。

答案 7 :(得分:-3)

为什么要问为什么

尝试获取长度,如果异常返回false

def haslength(seq):
    try:
        len(seq)
    except:
        return False
    return True