View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All

Iterator in Python: How Iteration Works with Practical Examples

Updated on 29/05/20255,851 Views

Iterator in Python is a powerful programming concept that allows you to access elements of a collection one at a time without using indexing. It is commonly used when working with loops, large datasets, or when memory efficiency is a concern. Python provides built-in support for iterators through special methods and functions, making iteration simple and readable. 

In this article, you will explore what an iterator is and how it differs from an iterable. Then, you will go through step-by-step examples ranging from basic to advanced levels. You’ll also learn when to use iterators in real-life situations, how the StopIteration exception works, and how to implement your own iterator using a class.

Pursue our Software Engineering courses to get hands-on experience!

What is an Iterator in Python?

An iterator in Python is an object that enables you to step through a sequence of elements one item at a time. It does not rely on index positions. Instead, it uses a specific set of methods to access each item sequentially.

To qualify as an iterator, an object must follow the iterator protocol. That means it must implement two built-in methods: __iter__() and __next__().  The __iter__() method returns the iterator object itself. The __next__() method returns the next item from the collection. If there are no items left, it raises a StopIteration exception.

You can create an iterator from an iterable (like a list or tuple) using Python’s built-in iter() function. Then, you can fetch elements one by one using the next() function.

Take your skills to the next level with these top programs:

Syntax of Iterator in Python

Here’s the syntax:

iterator = iter(iterable_object)  # Create an iterator from an iterable
item = next(iterator) # Get the next item from the iterator

Here, 

  • iterable_object: Any object like list, tuple, or string that supports iteration.
  • iter(): Initializes and returns an iterator object.
  • next(): Retrieves the next item from the iterator. Raises StopIteration when no items remain.

Let’s break down the syntax by creating a simple iterator manually using a custom class. This will help you understand how the iterator protocol works behind the scenes.

# Define a custom iterator class
class CountUpTo:
def __init__(self, max_value):
self.max = max_value # Maximum number to count up to
self.current = 1 # Start from 1

def __iter__(self):
return self # Return the iterator object itself

def __next__(self):
if self.current <= self.max:
num = self.current
self.current += 1 # Move to the next number
return num
else:
raise StopIteration # Stop when the limit is reached

# Create an instance of the iterator
counter = CountUpTo(3)

# Use the iterator manually with next()
print(next(counter)) # Output: 1
print(next(counter)) # Output: 2
print(next(counter)) # Output: 3

Output:

1

2

3

Explanation:

  • Class Definition:
    • We define a class CountUpTo that will count from 1 to a given maximum.
    • The __init__() method sets up the starting and maximum values.
  • Iterator Protocol:
    • __iter__() returns the iterator object itself. This is required for use in loops.
    • __next__() checks if the current number is within the allowed range.
      • If yes, it returns the current number and increments it.
      • If not, it raises a StopIteration exception, signaling the end of iteration.
  • Usage:
    • We create an object counter using CountUpTo(3).
    • Calling next(counter) three times gives us the numbers 1, 2, and 3.
    • A fourth call would raise StopIteration (not shown here to avoid interruption).

Iterator in Python Example

To fully understand how an iterator in Python works, it's helpful to see real examples in action. We will begin with a simple use case, move to a more controlled iteration using exception handling, and finally create a custom iterator with advanced behavior.

Beginner Level

# Create a list of students
students= ["Anil", "Kunal", "Harsh"]

# Get the iterator object using iter()
student_iterator = iter(students)

# Access each item using next()
print(next(student_iterator)) # Output: Anil
print(next(student_iterator)) # Output: Kunal
print(next(student_iterator)) # Output: Harsh

Output:

Anil

Kunal

Harsh

Explanation:

  • We start with a simple list of students.
  • Using iter(students), we get an iterator object.
  • Each call to next(student_iterator) returns the next student in the sequence.

Intermediate Level

Now let’s manually handle the StopIteration exception. This gives us better control, especially when we don’t know the exact size of the data.

# Define a list of numbers
numbers = [10, 20, 30]

# Get the iterator object
num_iter = iter(numbers)

# Use a while loop with exception handling
while True:
try:
# Print the next number
print(next(num_iter))
except StopIteration:
# Break the loop when iteration ends
break

Output:

10

20

30

Explanation:

  • The iterator num_iter is created from the list.
  • A while True loop is used to keep fetching values.
  • The next() call is wrapped in a try-except block.
  • When StopIteration is raised, the loop exits gracefully.
  • This method is useful when building reusable or dynamic iteration logic.

Must Explore: String split() Method in Python

Advanced Level

At the advanced level, you may want to create your own iterator to control how and when values are produced. This is useful when working with large datasets, mathematical sequences, or custom traversal logic. 

Let's understand how to build a custom iterator in Python that generates square numbers up to a defined limit.

# Custom iterator that generates square numbers from 1 to a given limit
class SquareNumbers:
def __init__(self, limit):
self.limit = limit # Upper bound for square values
self.num = 1 # Start from number 1

def __iter__(self):
return self # The __iter__() method returns the iterator object itself

def __next__(self):
if self.num <= self.limit:
result = self.num ** 2 # Calculate square of current number
self.num += 1 # Move to the next number
return result
else:
raise StopIteration # End iteration when limit is reached

# Create an instance of the custom iterator
squares = SquareNumbers(5)

# Iterate through the custom iterator and print each square number
for square in squares:
print(square)

Output:

1

4

9

16

25

Explanation:

  • We created a class SquareNumbers that follows the iterator protocol using __iter__() and __next__().
  • The constructor __init__() takes a limit and starts from number 1.
  • __next__() returns the square of the current number and increments it by 1.
  • When the current number exceeds the limit, StopIteration is raised.
  • The for loop uses this logic to print square numbers from 1² to 5².

Also read the Strip in Python article!

When to Use Iterators in Python?

You should use Python iterators when:

  • Working with large datasets: Iterators return one element at a time. This saves memory because it doesn’t load the entire dataset into memory like a list or tuple.
  • You need lazy evaluation: Iterators compute values only when needed. This "just-in-time" computation helps in saving resources.
  • Building custom loops: Iterators give you more control over iteration. You can stop, pause, or restart iteration using custom logic.
  • Reading data streams: Files, sockets, or APIs often provide data incrementally. Iterators handle this efficiently without needing to load the entire content.
  • Reusing the same iteration logic: You can wrap your logic in a class that follows the iterator protocol. This makes your code modular and reusable.
  • You want to avoid index errors: Iterators do not use indexing. Instead, they automatically handle the next element and stop when there’s nothing left.
  • Using for loops under the hood: Python’s for loop internally uses the iterator protocol. Understanding this helps you write cleaner and more Pythonic code.
  • Chaining multiple operations: You can combine iterators using tools like itertools to build data pipelines for transforming and processing.
  • Working with infinite sequences: You can design custom iterators that produce infinite outputs. This is impossible with standard data structures.

Difference Between Iterator and Iterable

Understanding the distinction between an iterator and an iterable is essential when working with loops and data structures in Python. While the two are closely related, they serve different purposes.

Here is a clear comparison between the two:

Feature

Iterable

Iterator

Definition

An object that can return an iterator

An object used to iterate through an iterable

Built-in Method

Must implement __iter__()

Must implement both __iter__() and __next__()

Examples

Lists, Tuples, Strings, Dictionaries, Sets

Objects returned by iter()

Can be looped using a for loop?

Yes

Yes

Need conversion to iterate manually?

Yes, use iter()

No, it is already ready to iterate

Can it be reused?

Yes, can create new iterator each time

No, once exhausted, it cannot be reused

Example: Using Iterator vs Iterable in an Attendance System

Suppose we have a list of employee names, and we want to call each one for attendance manually using an iterator. (The list itself is iterable.)

# List of employee names - this is an iterable
employee_names = ["Ravi", "Arjun", "Vikram", "Manoj"]

# Convert the iterable into an iterator
attendance_iterator = iter(employee_names)

# Calling out names one by one using the iterator
print("Marking Attendance:")
print(next(attendance_iterator)) # Output: Ravi
print(next(attendance_iterator)) # Output: Arjun
print(next(attendance_iterator)) # Output: Vikram
print(next(attendance_iterator)) # Output: Manoj

Output:

Marking Attendance:

Ravi

Arjun

Vikram

Manoj

Explanation:

  • employee_names is an iterable object (a list), meaning it can return an iterator.
  • We use iter(employee_names) to get an iterator in Python, called attendance_iterator.
  • The next() function is used to fetch names one by one for marking attendance.
  • This demonstrates how you can use an iterator to sequentially process each element of an iterable.
  • Once all names are called, calling next() again will raise a StopIteration error.

Must Explore: String split() Method in Python

Conclusion

Understanding how an iterator in Python works is essential for writing clean and efficient loops. Iterators allow you to traverse through elements in a collection one item at a time. They work with built-in types like lists, tuples, and dictionaries, and they can also be customized using classes. 

By mastering Python iterators, you gain more control over data traversal. And this is especially useful when working with large datasets or implementing custom sequences.

FAQs

1. What is a StopIteration Statement in Python?

The StopIteration statement in Python is used to signal that an iterator has no more items to return. When the __next__() method raises this exception, it stops the loop. This exception is automatically handled when using a for loop. However, when calling next() manually, you should handle it using a try-except block to avoid unexpected crashes.

2. How to Iterate Through an Iterable Object?

To iterate through an iterable object in Python, you can use a for loop or convert it into an iterator using the iter() function. Once it's an iterator, you can use next() to access elements one by one. This gives you more control over how and when items are accessed.

# Example of manual iteration using iter() and next()
cities = ["Mumbai", "Delhi", "Chennai"]
city_iterator = iter(cities)

print(next(city_iterator)) # Mumbai
print(next(city_iterator)) # Delhi
print(next(city_iterator)) # Chennai
  • iter() converts the list into an iterator.
  • next() retrieves the next value each time it's called.

3. How to Build a Custom Iterator in Python?

To build your own iterator in Python, create a class that implements the __iter__() and __next__() methods. This lets you generate values based on your own logic, like counting backwards or generating square numbers.

# Custom iterator to generate even numbers
class EvenNumbers:
def __init__(self, limit):
self.num = 2
self.limit = limit

def __iter__(self):
return self

def __next__(self):
if self.num <= self.limit:
result = self.num
self.num += 2
return result
else:
raise StopIteration

evens = EvenNumbers(10)
for val in evens:
print(val)
  • Generates even numbers starting from 2 up to a given limit.
  • Raises StopIteration when the sequence ends.

4. What is the Key Difference Between Iterable and Iterator in Python?

An iterable is any Python object you can loop over, like lists, strings, or sets. An iterator is an object returned by calling iter() on an iterable. Only iterators implement the __next__() method to fetch elements one at a time.

5. Can You Modify an Iterator While Iterating Over It?

Modifying an iterator while iterating over it is not safe. Doing so can lead to skipped values, infinite loops, or runtime errors. It’s better to create a copy of the data or collect changes to apply later.

6. Why Is the Iterator Protocol Useful in Python?

The iterator protocol in Python makes it possible to write generic code that can work with any iterable. It allows delayed or lazy computation, efficient memory use, and simplifies loop syntax with for and in.

7. Can You Use Iterators With Generators in Python?

Yes, you can. In fact, Python generators are a simplified way to create iterators. A generator function uses the yield keyword and automatically implements both __iter__() and __next__() behind the scenes.

# Generator that yields square values
def square_gen(limit):
for i in range(1, limit + 1):
yield i ** 2

for val in square_gen(3):
print(val)

8. What Happens If You Reuse an Iterator in Python?

Once an iterator is exhausted, it cannot be reused. Calling next() after it's done will raise StopIteration. If you need to start over, you must create a new iterator from the iterable.

9. Is It Possible to Convert an Iterator to a List?

Yes, you can convert an iterator to a list using the list() constructor. This is helpful when you want to store or reuse the values generated by the iterator.

nums = iter([1, 2, 3])
print(list(nums)) # Output: [1, 2, 3]

10. How Does Lazy Evaluation Work in Iterators?

Iterators in Python use lazy evaluation, meaning they calculate values only when needed. This makes them memory-efficient, especially for large datasets or infinite sequences. You only compute one item at a time, which avoids loading everything into memory.

11. Why Should You Use a Python Iterator for Custom Objects?

Using iterators with custom objects gives you full control over how values are accessed and when the sequence should stop. This is useful for tasks like pagination, file processing, or simulating data streams without preloading data into memory.

image

Take our Free Quiz on Python

Answer quick questions and assess your Python knowledge

right-top-arrow
image
Join 10M+ Learners & Transform Your Career
Learn on a personalised AI-powered platform that offers best-in-class content, live sessions & mentorship from leading industry experts.
advertise-arrow

Free Courses

Explore Our Free Software Tutorials

upGrad Learner Support

Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)

text

Indian Nationals

1800 210 2020

text

Foreign Nationals

+918068792934

Disclaimer

1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.

2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.