Python: check if an object is a sequence

PythonIf StatementSequenceSequences

Python Problem Overview


In python is there an easy way to tell if something is not a sequence? I tried to just do: if x is not sequence but python did not like that

Python Solutions


Solution 1 - Python

iter(x) will raise a TypeError if x cannot be iterated on -- but that check "accepts" sets and dictionaries, though it "rejects" other non-sequences such as None and numbers.

On the other hands, strings (which most applications want to consider "single items" rather than sequences) are in fact sequences (so, any test, unless specialcased for strings, is going to confirm that they are). So, such simple checks are often not sufficient.

In Python 2.6 and better, abstract base classes were introduced, and among other powerful features they offer more good, systematic support for such "category checking".

>>> 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

You'll note strings are still considered "a sequence" (since they are), but at least you get dicts and sets out of the way. If you want to exclude strings from your concept of "being sequences", you could use collections.MutableSequence (but that also excludes tuples, which, like strings, are sequences, but are not mutable), or do it explicitly:

import collections

def issequenceforme(obj):
    if isinstance(obj, basestring):
        return False
    return isinstance(obj, collections.Sequence)

Season to taste, and serve hot!-)

PS: For Python 3, use str instead of basestring, and for Python 3.3+: Abstract Base Classes like Sequence have moved to collections.abc.

Solution 2 - Python

For Python 3 and 2.6+, you can check if it's a subclass of collections.Sequence:

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

In Python 3.7 you must use collections.abc.Sequence (collections.Sequence will be removed in Python 3.8):

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

However, this won't work for duck-typed sequences which implement __len__() and __getitem__() but do not (as they should) subclass collections.Sequence. But it will work for all the built-in Python sequence types: lists, tuples, strings, etc.

While all sequences are iterables, not all iterables are sequences (for example, sets and dictionaries are iterable but not sequences). Checking hasattr(type(obj), '__iter__') will return True for dictionaries and sets.

Solution 3 - Python

Since Python "adheres" duck typing, one of the approach is to check if an object has some member (method).

A sequence has length, has sequence of items, and support slicing [doc]. So, it would be like this:

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

They are all special methods, __len__() should return number of items, __getitem__(i) should return an item (in sequence it is i-th item, but not with mapping), __getitem__(slice(start, stop, step)) should return subsequence, and __setitem__ and __delitem__ like you expect. This is such a contract, but whether the object really do these or not depends on whether the object adheres the contract or not.

Note that, the function above will also return True for mapping, e.g. dict, since mapping also has these methods. To overcome this, you can do a heavier work:

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

But most of the time you don't need this, just do what you want as if the object is a sequence and catch an exception if you wish. This is more pythonic.

Solution 4 - Python

For the sake of completeness. There is a utility is_sequence in numpy library ("The fundamental package for scientific computing with Python").

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

But it accepts sets as sequences and rejects strings

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

The code looks a bit like @adrian 's (See numpy git code), which is kind of shaky.

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

Solution 5 - Python

The Python 2.6.5 documentation describes the following sequence types: string, Unicode string, list, tuple, buffer, and xrange.

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

Solution 6 - Python

why ask why

try getting a length and if exception return false

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

Solution 7 - Python

Why are you doing this? The normal way here is to require a certain type of thing (A sequence or a number or a file-like object, etc.) and then use it without checking anything. In Python, we don't typically use classes to carry semantic information but simply use the methods defined (this is called "duck typing"). We also prefer APIs where we know exactly what to expect; use keyword arguments, preprocessing, or defining another function if you want to change how a function works.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnicotineView Question on Stackoverflow
Solution 1 - PythonAlex MartelliView Answer on Stackoverflow
Solution 2 - PythonAl SweigartView Answer on Stackoverflow
Solution 3 - Pythonfikr4nView Answer on Stackoverflow
Solution 4 - Pythonloved.by.JesusView Answer on Stackoverflow
Solution 5 - PythonDavid AntaramianView Answer on Stackoverflow
Solution 6 - PythonadrianView Answer on Stackoverflow
Solution 7 - PythonMike GrahamView Answer on Stackoverflow