4

I can think of two ways to determine whether an object is a sequence:

  • hasattr(object, '__iter__').
  • And whether calling iter(object) raises a TypeError.

As it is most Pythonic to ask forgiveness than to ask permission, I'd use the second idiom, although I consider it more ugly (additionally, raising an exception once you've caught the TypeError to determine that the object isn't a sequence would yield an undesirable "double-exception" stack trace).

Ultimately, is checking that an object defines an __iter__ method exhaustive enough to determine whether an object is a sequence? (In older versions of Python, for example, str didn't define an __iter__ method; I've also heard that some objects can also simply define and use __getitem__ without defining an __iter__ and act like a sequence.) Or is defining __iter__ the contract of a sequence?

Humphrey Bogart
  • 7,423
  • 14
  • 52
  • 59
  • Of what I could find online, [this discussion](http://bytes.com/topic/python/answers/514838-how-test-if-object-sequence-iterable) seemed most relevant, although it's quite old; [this StackOverflow question](http://stackoverflow.com/questions/1835018/python-check-if-an-object-is-a-list-or-tuple-but-not-string) was somewhat related. – Humphrey Bogart Nov 24 '10 at 14:36

1 Answers1

5

Use isinstance(obj, collections.Sequence). Abstract base classes are exactly for this. They didn't exist prior to 2.6 though. In case you're forced to use older versions, you're out of luck and better stick with EAFP.

  • +1. I was literally about to post the same thing. But note that in the pre-2.6 case, non-sequences have `__iter__`, e.g. `dict`. I'm not sure on what the best way to deal with this is. – aaronasterling Nov 24 '10 at 14:43
  • 1
    The best way to deal with it might be documenting that the code can give unexpected/wrong results when passed a non-sequence iterable. Actually, that should propably be done no matter if and how one tries to hack around this... –  Nov 24 '10 at 14:51
  • 1
    shouldn't it be `isinstance(obj, collections.Sequence)`? – SilentGhost Nov 24 '10 at 15:03
  • So, in order to create a *correct* sequence class, should it subclass `collections.Sequence`? Does the `isinstance` function actually check if it subclasses the class, or does it only check to see if it implements the appropriate methods? – Humphrey Bogart Nov 24 '10 at 17:34
  • It checks if the object is an instance of a subclass or of a class that has been registered as a "virtual subclass" (see the abc module for info and further links http://docs.python.org/library/abc.html). E.g. `isinstance({}, collections.Sequence)` yields `False`. –  Nov 24 '10 at 17:37