Python Iterators and Iterables Explained
SkillVeris Team
Engineering Team

An iterable is any object you can loop over, like a list or string; an iterator is the object that yields its items one at a time.
In this guide, you'll learn:
- Calling iter() on an iterable returns an iterator, and calling next() on the iterator produces the next value.
- A for loop is syntactic sugar that calls iter() once and next() repeatedly until StopIteration is raised.
- Iterators are lazy: they produce values on demand, which saves memory for large or infinite sequences.
- Generators are the easiest way to create iterators, using yield instead of return.
1Iterable vs Iterator: The Core Difference
An iterable is any object you can loop over, such as a list, tuple, string, or dictionary. An iterator is the object that actually produces those values one at a time and remembers its position between values. Every iterator is iterable, but not every iterable is an iterator. The distinction explains how Python's for loops really work.
You turn an iterable into an iterator by calling iter() on it. You then pull values from the iterator by calling next() until there are none left, at which point Python raises StopIteration. A for loop does exactly this behind the scenes so you never have to manage it manually.
2The Iterator Protocol
Python's iteration is built on a simple contract called the iterator protocol. An iterable defines __iter__, which returns an iterator. An iterator defines both __iter__ (returning itself) and __next__, which returns the next value or raises StopIteration when finished. Understanding this protocol demystifies every loop you write.
- nums = [1, 2, 3] # a list is iterable
- it = iter(nums) # get an iterator from it
- next(it) # 1
- next(it) # 2
- next(it) # 3
- next(it) # raises StopIteration
🔑Key Takeaway
A for loop is just iter() plus repeated next() calls, stopping cleanly when StopIteration is raised. Nothing more mysterious than that.
3How a for Loop Really Works
When you write for x in nums, Python first calls iter(nums) to get an iterator, then repeatedly calls next() on it, assigning each result to x, until StopIteration signals the end. The two loops below are functionally identical; the second shows the machinery the first hides.
- for x in nums: # the friendly version
- print(x)
- it = iter(nums) # the manual equivalent
- while True:
- try:
- x = next(it)
- except StopIteration:
- break
- print(x)
4Why Laziness Matters
Iterators are lazy, meaning they compute each value only when asked rather than building the whole sequence up front. This is what lets you loop over a huge file line by line, or even an infinite sequence, without exhausting memory. A list of a billion numbers would not fit in RAM, but an iterator that yields them one at a time will.
⚠️Watch Out
Iterators are single-use. After a loop drains one, iterating again yields nothing. If you need to loop twice, keep the underlying iterable (like a list) or rebuild the iterator.
One-Time Use
An iterator is consumed as you go. Once exhausted, it will not restart; you must create a fresh one. This trips up beginners who expect to loop over the same iterator twice and find it empty the second time.
5Generators: Iterators Made Easy
The simplest way to create an iterator is a generator. A generator function uses yield instead of return; each yield hands back a value and pauses, resuming where it left off on the next call. Python builds the __iter__ and __next__ machinery for you automatically.
- def countdown(n):
- while n > 0:
- yield n # pause and return a value
- n -= 1
- for x in countdown(3): # 3, 2, 1
- print(x)
- squares = (x*x for x in range(5)) # generator expression
6Building a Custom Iterator Class
You can make any class iterable by implementing the protocol directly. This class counts up to a limit, returning itself from __iter__ and producing values from __next__ until it raises StopIteration.
- class UpTo:
- def __init__(self, limit):
- self.limit = limit
- self.current = 0
- def __iter__(self):
- return self
- def __next__(self):
- if self.current >= self.limit:
- raise StopIteration
- self.current += 1
- return self.current
7Common Mistakes to Avoid
Iteration bugs usually stem from misunderstanding an iterator's one-time, lazy nature.
- Expecting to reuse an exhausted iterator; create a new one instead.
- Calling len() on a generator, which has no length until consumed.
- Confusing an iterable (a list) with its iterator (from iter()).
- Forgetting to raise StopIteration in a custom __next__, causing an infinite loop.
- Converting a huge lazy iterator to a list needlessly, discarding the memory benefit.
8Key Takeaways
Grasping iteration unlocks generators, comprehensions, and memory-efficient code.
- An iterable can be looped over; an iterator produces values one at a time.
- iter() makes an iterator; next() pulls the next value.
- for loops call iter() once and next() until StopIteration.
- Iterators are lazy and single-use, saving memory.
- Generators with yield are the easiest way to build iterators.
9Frequently Asked Questions
Q: What is the difference between an iterable and an iterator? A: An iterable is any object you can loop over, like a list or string. An iterator is the object that actually yields values one at a time and tracks its position. You get an iterator from an iterable by calling iter().
Q: Why does looping over my iterator a second time give nothing? A: Iterators are single-use. Once a loop drains one, it is exhausted. To iterate again, keep the original iterable (such as a list) or create a fresh iterator.
Q: What is a generator and how does it relate? A: A generator is the easiest way to make an iterator. A function that uses yield instead of return becomes a generator, and Python builds the iterator machinery for you automatically.
Q: Why use iterators instead of lists? A: Iterators are lazy, producing values on demand instead of all at once. This lets you process huge files or infinite sequences without loading everything into memory.
Related Reading
Get The Print Version
Download a PDF of this article for offline reading.
About the Publisher
SkillVeris Team
Engineering Team
Our engineering writers turn abstract code concepts into hands-on, project-driven learning experiences.
View all postsRelated Posts
Never miss an update
Get the latest tutorials and guides delivered to your inbox.
No spam. Unsubscribe anytime.