Login Register

What Is an Iterator In Python?

What Is an Iterator?

  • An iterator in Python is a special object that allows you to access any item one by one from a collection like a list, tuple, string, etc.
  • We don’t need to know how the collection is stored internally.
  • It’s like a remote control, when we press the button, it will show us one particular item at a time. We don’t see all items at once.

In simple words, whenever we ask for an iterator, it will return the next value every time.

An iterator has two important methods:

1) __iter__(): This method will prepare the object to start iterating, and returns the iterator object itself.

2) __next__(): This method returns the next item in the sequence. Whenever it has a value to return, it gives a special signal called StopIteration.

StopIteration is the Python official way to tell us “No more items left. You reached the end.”


What Is Iteration Protocol In An Iterator?

Python iteration protocol refers to a simple rule to decide how Python moves through items one by one. This protocol is useful in for…loops and functions like next() to work easily.

Python provides two components to use these protocols:

  • Iterable
  • Iterator

1) Iterable:

An iterable contains a collection of values and gives us an iterator when asked. It’s like a full box of items; you can ask the box for a helper who will hand out the items one by one.

Examples of iterable objects:

2) Iterator:

An iterator is the helper object that actually delivers items one by one from the iterable. It remembers where it stopped and gives you the next element each time you call next().

Imagine an iterable is a playlist and an iterator is a music player.

  • The playlist contains all songs.
  • The music player plays the next song each time you press “Next”.
  • When the playlist ends, it stops and shows “No more songs”.

Examples of Iterators

First we will create one iterator from a list, and then we create out own custom iterator class.

Example 1: Using an Iterator on a List

  • When you create an iterator from a list, Python gives you a special object that remembers where it was last time.
  • Every time you call next(), it moves forward and gives the next item. When all items are finished, Python stops.
# Creating a list of mixed day temperatures
temperatures = [28, 30, 27, 29]

# Creating an iterator from the list
temp_iter = iter(temperatures)

print("Morning:", next(temp_iter)) # 28
print("Noon:", next(temp_iter)) # 30
print("Evening:", next(temp_iter)) # 27
print("Night:", next(temp_iter)) # 29

Output of the code:

Morning: 28
Noon: 30
Evening: 27
Night: 29

Example 2: Manually Creating a Custom Iterator

Now we create a SkipCounter (counts by 2). This iterator returns every second number between a start and end value.

class SkipCounter:
def __init__(self, start, end):
self.current = start
self.end = end

def __iter__(self):
return self

def __next__(self):
if self.current <= self.end:
value = self.current
self.current += 2 # Jump by 2 every time (unique behavior)
return value
else:
raise StopIteration

# Using the custom iterator
counter = SkipCounter(3, 11)

for step in counter:
print(step)

Output of the code:

3
5
7
9
11

How Can We Use Iterator In Loops?

A for loop works front of use, but Python secretly uses an iterator behind the scenes. Whenever we write the following command:

for item in some_collection:

Python does two things:

  • Calls the __iter__() method of the collection to get an iterator.
  • Repeatedly calls __next__() on that iterator to get one item at a time.
  • So if you don’t write next() manually, Python is using it in the background.

Example 1: Looping Over a Tuple

# A normal tuple
scores = (15, 25, 35, 45)

# Python will secretly use an iterator when we loop
for score in scores:
print("Current score:", score)

Output:

Current score: 15
Current score: 25
Current score: 35
Current score: 45

In this code:

  • Python turns scores into an iterator: iter(scores)
  • Then Python repeatedly calls: next(iterator)
  • The loop ends when StopIteration is raised internally.

Example 2: Custom Iterator Used Inside a Loops

The iterator will return characters at positions: 0, 2, 4, 6…

# Custom iterator: gives alternate letters from a word
class AlternateLetters:
def __init__(self, text):
self.text = text
self.index = 0

def __iter__(self):
return self

def __next__(self):
if self.index < len(self.text):
letter = self.text[self.index]
self.index += 2 # jump by 2 (unique logic)
return letter
else:
raise StopIteration

# Using our iterator inside a loop
word = AlternateLetters("PYTHON")
for ch in word:
print(ch)

Explanation:

P
T
O
  • This code return every second character

Advantages of Using Iterators

  1. Memory Efficiency: Iterators reduce memory usage because they fetch data one element at a time.
  2. Lazy Evaluation: Elements are computed only when needed.
  3. Flexibility: Iterate over various data types seamlessly.

Common Pitfalls with Iterators

1) Iterator Exhaustion: An iterator can move forward only once. After it reaches the last element, it becomes “empty” and cannot start again unless you create a new iterator.

For example:

items = [3, 6, 9]
my_iter = iter(items)

for value in my_iter:
print(value) # Prints all values

for value in my_iter:
print(value) # Prints nothing because iterator is already finished

2) StopIteration Exception: When you manually call next() on an iterator, and there are no more items left, Python raises a special error:

StopIteration

Example code:

numbers = iter([10, 20])

print(next(numbers)) # 10
print(next(numbers)) # 20
print(next(numbers)) # StopIteration (because no more items)