Explain Codes LogoExplain Codes Logo

In Python, how do I determine if an object is iterable?

python
iterable
collections
iterators
Alex KataevbyAlex Kataev·Oct 7, 2024
TLDR

If your code is thirsting for a quick sip of knowledge, here's the quickest way to check if something is iterable: use iter(). If it laughs in the face of a TypeError, then your object has the power to deliver an iteration performance!

def is_iterable(obj): try: iter(obj) # "Can you juggle?" we ask politely. return True except TypeError: return False # If it throws TypeError tomatoes, it's a "no". # Showtime! Is iterable, or isn't it? print(is_iterable([1, 2, 3])) # True... an array's born to juggle! print(is_iterable(1)) # False... integers can't juggle :(

Following Pythonic wisdom

EAFP, not your average TLA (Three Letter Acronym)

A wise Pythonista once said: "It's Easier to Ask for Forgiveness than Permission" (EAFP). Sounds rebellious, but it's just saying to boldly try and catch exceptions if they bother to show up.

collections.abc, the backstage crew

You can also check iterable star power using collections.abc. Behind that very non-musical name lies the Iterable abstraction, ready to let you know if your object can join the iteration performance.

from collections.abc import Iterable def is_iterable(obj): return isinstance(obj, Iterable) # Basically asking: "Got a backstage pass?" # So, got the pass or not? print(is_iterable([1, 2, 3])) # True... it's in the band! print(is_iterable('hello')) # True... even a string can play! print(is_iterable(1)) # False... a number won't play ball.

Behind the iterable stage curtains

If you dig deeper, you'll find a __iter__ method hiding behind the iterable magic. But there's a twist: Python gives the "iterable" title to objects implementing __getitem__ as well. iter() knows this secret, isinstance(obj, Iterable) doesn't.

The audition for custom classes

Creating a custom class? Make sure to show them you can juggle by implementing __iter__. Sure, hasattr(obj, '__iter__') can check for you, but it's like a biased judge; it might not catch a ‘getitem’ act.

The new kid on the block: typing

And guess what? Python 3.5 brought a shiny module, typing, which includes Iterable. It can help check your iterability before the performance (type annotation).

The juggling custom classes

When you define a custom iterable class, you're setting up your own juggling act. Get that __iter__ method up and running, and you'll be juggling in no time:

class CustomIterable: def __iter__(self): # Implement the juggling act (__iter__ method) pass

Shadows on the iterable stage

While stage lights shine differently on different objects, remember:

  • Python built-ins like dict can juggle without explicitly showing how (providing keys when iterated). It's magic!
  • External factors like a UserDict wrapper can mess up juggling (iterability). Handle with care!
  • There's no way to predict a performer's sanity (iterator validity) without watching them juggle (iter()).

The hasattr critic

Avoiding try/except? Well, hasattr() can give you a verdict too. But don't trust it blindly, it's a critic reviewing the juggling act without watching the full performance:

def is_iterable(obj): return hasattr(obj, '__iter__') or hasattr(obj, '__getitem__') # WARNING: This critic is known to be partial, be cautious!

A backstage tour to handling exceptions

Watch out for the Typography

hasattr() sometimes sells tickets for a show that isn't playing. It tells you there's a method, but not if it works as it should or the object can return an iterator.

Constructing your own iterator

Python helps you create an iterator for objects with __getitem__ like a helping backstage crew, piloting an underlying iteration over objects, even without an explicit __iter__.

The final dress rehearsal

Sometimes, a dress rehearsal (controlled environment iteration) is the only way to be absolutely sure about your juggling act (iterable object). Watch the behavior, deal with the tantrums (exceptions), and you'll know if it's showtime or not.