Master Iterables and Iterators in Python with Examples

Python Iterators is one of the most crucial concepts in programming that can be utilized to traverse and process data sequences efficiently. These iterators offer a versatile approach for handling several types of data, whether they are collections or infinite sequences.

Today’s guide is all about Python iterators, their working, customized iterators, using built-in functions for iterations, and how infinite iterators work. So, let’s begin this journey!

What is Iteration in Python

In Python, iterators are the fundamental concepts that permit sequential access to the element within a collection. They enable you to iterate over the data efficiently.

An iterator refers to an object that can be iterated or looper over. Ultimately, it provides access to one element at a time. More specifically, iterators offer a way for traversing elements within a container, which can be tuples, lists, or custom objects.

Difference Between Iterators and Iterables

A Python iterable is capable of traversing and returning one element at a time. It can be utilized for creating iterators. On the other hand, iterators are the objects that implement the “__next__()” and “__iter__()” methods and enable sequential access to the respective elements.

Note: Every iterator is iterable. However, not every iterable is an iterator.

In the given example, we will create an iterable “numbers” list. Then, fetch an iterator from the iterable with the “iter()” function.

After that, the “next()” function is utilized for retrieving the element sequentially from the iterator.

numbers = [11, 22, 33, 44, 55]
iterable = iter(numbers)
print(next(iterable))
print(next(iterable))
Difference Between Iterators and Iterables
Difference Between Iterators and Iterables

How Iterators Work in Python

In Python, iterators are based on the iterator protocol which involves two methods, “__iter__()” and “__next__()“.

The “__iter__()” method outputs the iterator object itself. While the “__next__()” method displays the iterator’s next value.

However, the “StopIterationexception will be triggered by the “__next__()” method, if there exist no more elements to be accessed.

Here, we have created a custom iterator “Countdown” that generates a countdown sequence. Next, the “_iter__()” method has been called for returning the iterator object itself.

Then, the “__next__()” method defines the iteration logic.

class Countdown:
    def __init__(self, start):
        self.start = start
   
    def __iter__(self):
        return self
   
    def __next__(self):
        if self.start <= 0:
            raise StopIteration
        value = self.start
        self.start -= 1
        return value

countdown = Countdown(5)
for num in countdown:
    print(num, end=' ')
How Iterators Work in Python
How Iterators Work in Python

Create Custom Iterators in Python

Python permits the creation of custom iterators by implementing the discussed iterator protocol in user-defined classes. This process is based on defining the “__iter_()” and “__next__()” methods within the class.

Additionally, custom iterators can offer specialized behavior and control over the iteration process.

According to the provided code, we will create a custom iterator named “Squares” that generates square numbers up to the defined limit. Likewise, the “__iter__()” method outputs the iterator object itself, and the “__next__()” method specifies the logic for generating the square numbers.

class Squares:
    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
        result = self.current ** 2
        self.current += 1
        return result

squares_iterator = Squares(4)
for square in squares_iterator:
    print(square, end=' ')
Create Custom Iterators in Python
Create Custom Iterators in Python

Using the For Loop with Iterators in Python

You can utilize the for loop for iterating over the elements. More specifically, when the for loop is used with an iterator, it automatically handles the process of fetching the elements and iterates until no more elements are left.

numbers = [10, 20, 30, 40, 50]
for num in numbers:
    print(num, end=' ')
Using the For Loop with Iterators in Python
Using the For Loop with Iterators in Python

Built-in Functions for Iteration

Python offers a set of built-in functions that assist in iterating and manipulating the data. For instance, the functions such as “map()“, “zip()“, and “filter()” enable you to efficiently process the iterables and create new ones.

These functions can be utilized for implementing the concept of functional programming.

Using map() Function

In this example, the map() function applied a lambda function to each element for calculating their squares and the print() function displayed the corresponding values on the console.

numbers = [10, 20, 30, 40, 50]
squared = map(lambda x: x**2, numbers)

print(list(squared))
Using map() Function
Using map() Function

Using filter() Function

Here, the filter() function utilized the lambda function to fetch the elements that satisfy the given condition “ x % 2 == 0“.

numbers = [10, 20, 30, 40, 50]
filtered = filter(lambda x: x % 2 == 0, numbers)

print(list(filtered))
Using filter() Function
Using filter() Function

Using zip() Function

In this case, the zip() method combines the multiple iterable element-wise, and the output is transformed into respective lists.

numbers = [1, 2, 3, 4, 5]
squared = map(lambda x: x**2, numbers)
filtered = filter(lambda x: x % 2 == 0, numbers)
zipped = zip(numbers, squared)

print(list(zipped))
Using zip() Function
Using zip() Function

Infinite Iterators in Python

Infinite iterators can be used for generating elements endlessly in Python. These iterators offer a continuous stream of values. You can utilize these iterators for enabling applications such as data generators, numerical simulations, and more.

Note: Carefully use infinite iterators to avoid infinite loops.

Here, in the given program, we will first create an infinite iterator “InfiniteCounter” that generates an increasing count. Then, the “__next__()” method continuously adds the count and produces an infinite sequence.

The iterator in a loop is used for demonstrating the method to utilize and control the infinite iterators effectively.

class InfiniteCounter:
    def __init__(self):
        self.count = 0
   
    def __iter__(self):
        return self
   
    def __next__(self):
        result = self.count
        self.count += 1
        return result

infinite_iterator = InfiniteCounter()
for _ in range(5):
    print(next(infinite_iterator), end=' ')
Infinite Iterators in Python
Infinite Iterators in Python

Create Efficient Iterators with Generators Function

Python generators offer a memory-efficient way of creating iterators. Generators are the functions that utilize the yield keyword for generating the values one at a time as per requirement. This feature minimizes memory usage and also improves performance.

Now, we will define a generator function named “fibonacci_sequence()” that yields the Fibonacci number. Here, the yield statement generates the values and the generator maintains its state between iterations.

def fibonacci_sequence():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fibonacci_gen = fibonacci_sequence()
for _ in range(5):
    print(next(fibonacci_gen), end=' ')
Create Efficient Iterators with Generators Function
Create Efficient Iterators with Generators Function

Chaining Iterators Using chain() and zip() Function

Python itertools modules offer different functions to chain and combine multiple iterators. The chain() function combines multiple iterables into a single sequence. On the other hand, the zip() function combines the elements from the multiple iterable element-wise.

for item in result2:from itertools import chain, zip_longest

numbers = [1, 2, 3]
letters = ['A', 'B', 'C']
result1 = chain(numbers, letters)
print('With chain():')  
for item in result1:
   
    print(item, end=' ')  

result2 = zip_longest(numbers, letters, fillvalue='X')
print('\nWith zip():')

    print(item, end=' ')  
Chaining Iterators Using chain() and zip() Function
Chaining Iterators Using chain() and zip() Function

That’s all from this effective guide related to Python Iterators.

Conclusion

Python iterators are a robust tool for improving the efficiency of your programs. By utilizing them, you can easily navigate through the collections, customize your own iterators, and use built-in functions for iterations.

So, consider these valuable assets and enhance your coding skills to create efficient Python projects.

Want to explore and learn more related to Python, do check out our dedicated Python Tutorial Series!

If you read this far, tweet to the author to show them you care. Tweet a thanks
As a professional content writer with 3 years of experience, I specialize in creating high-quality, SEO-optimized content that engages, attracts, and retains the audience.

Each tutorial at GeeksVeda is created by a team of experienced writers so that it meets our high-quality standards.

Join the GeeksVeda Weekly Newsletter (More Than 5,467 Programmers Have Subscribed)
Was this article helpful? Please add a comment to show your appreciation and support.

Got Something to Say? Join the Discussion...