In Python, an iterator is an object that enables traversal over a collection of items, one at a time.
It follows the iterator protocol, which involves implementing the
__iter__()
and__next__()
methods.The
__iter__()
method returns the iterator object itself, while__next__()
retrieves the next element from the collection.When there are no more elements, a
StopIteration
exception is raised.
Iterating over lists
Approach -1: Iterating over the list directly
list = [2, 4, 6, 8, 10]
for value in list:
print(value, end=' ')
#Output = 2 4 6 8 10
In this approach, the entire list
[2, 4, 6, 8, 10]
is stored in memory.The
for
loop iterates over each element of the list, processing them one by one.Memory usage is relatively higher since the complete list is stored in memory throughout the loop execution.
Approach -2: Using an iterator object
list = [2, 4, 6, 8, 10]
iter_obj = iter(list) # <list_iterator object at 0x7fcf3519f670>
print(next(iter_obj)) # Output = 2
print(next(iter_obj))# Output = 4
print(next(iter_obj))# Output = 6
print(next(iter_obj))# Output = 8
print(next(iter_obj))# Output = 10
In this approach, an iterator object is explicitly created using
iter(list)
.Each call to
next(iter_obj)
retrieves the next element from the iterator, without storing the entire list in memory.Only one element at a time is accessed and processed, reducing memory usage.
As elements are fetched one by one, the memory footprint is lower compared to
Built-in Iterators in Python
Python provides several built-in iterators and iterable objects that simplify common iteration tasks. Let's explore a few of them:
range()
The
range()
function generates a sequence of numbers within a specified range. It can be used directly as an iterator.for i in range(5): print(i,end = " ") #Output = 0 1 2 3 4 5
enumerate()
The
enumerate()
function is useful when we need both the index and value of each element while iterating over a sequence.my_list = ['Nirmal', 'Niraj', 'Retrica'] for index, value in enumerate(my_list): print(f"Index: {index}, Value: {value}")
Output :
Index: 0, Value: nirmal Index: 1, Value: niraj Index: 2, Value: retrica
zip()
:The
zip()
function combines multiple iterables into a single iterator. It pairs up corresponding elements from each iterable.names = ['Nirmal', 'Niraj', 'Retrica'] ages = [23, 20, 27] for name, age in zip(names, ages): print(f"Name: {name}, Age: {age}")
Output :
Name: Nirmal, Age: 23 Name: Niraj, Age: 20 Name: Retrica, Age: 27
Itertools Module
The itertools
module is a powerful tool that provides various functions for efficient iteration and a combination of iterables. It extends the capabilities of built-in iterators.
Some modules are :
1. itertools.cycle()
This creates an iterator that cycles through elements of an iterable indefinitely.
import itertools
name = ["nirmal", "niraj", "retrica"]
myloopy = itertools.cycle(name)
print(next(myloopy)) # Output: nirmal
print(next(myloopy)) # Output: niraj
print(next(myloopy)) # Output: retrica
2. itertools.chain()
This combines multiple iterables into a single sequence.
import itertools
inter1 = itertools.chain("nirmal", "pandey")
print(list(inter1)) # Output: ['n', 'i', 'r', 'm', 'a', 'l', 'p', 'a', 'n', 'd', 'e', 'y']
itertools. accumulate()
This returns an iterator that produces accumulated sums of an iterable.
import itertools
num = [1, 2, 3, 4, 5, 6]
inter2 = itertools.accumulate(num)
print(list(inter2)) # Output: [1, 3, 6, 10, 15, 21]
4.itertools.repeat()
This generates an iterator that repeats a value a specified number of times.
import itertools
inter3 = itertools.repeat(10, 3)
print(list(inter3)) # Output: [10, 10, 10]
5: itertools.compress()
This filters an iterable based on the truth value of corresponding selectors.
import itertools
inter4 = itertools.compress("nirmal", [1, 0, 1, 0, 1, 1])
print(list(inter4)) # Output: ['n', 'r', 'a', 'l']
Custom Iterator
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.data):
raise StopIteration
value = self.data[self.index]
self.index += 1
return value
my_list = [1, 2, 3, 4, 5]
my_iter = MyIterator(my_list)
for item in my_iter:
print(item)
In this example, we create a custom iterator MyIterator
takes a list as input. The __iter__()
method returns the iterator object itself, and __next__()
fetches the next element from the list. Once there are no more elements, a StopIteration
exception is raised.