You must have used different data structures like python dictionary, list, tuple and set while programming. We often need to access the elements of these data structures in a sequential manner.
To iterate these data structures sequentially, we generally use for loops and index of elements. In this article, we will try to understand how we can access elements of a list or a tuple without using a for loop or the indices of the elements.
So, let’s dive into the concept of iterator and iterables in Python.
What is an iterable in Python?
A container object like a list or set can contain a lot of elements. If we can access the member elements of the container objects one at a time then the container object is called an iterable. In our programs we use different iterables like list, tuple, set, or dictionary.
Elements of any iterable can be accessed one at a time using a for loop as follows.
myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print("Elements of the list are:")
for element in myList:
print(element)
Output:
Elements of the list are:
1
2
3
4
5
6
7
8
9
10
In a for loop, we access all the elements from start till end. But, Consider a situation where we have to access the next element of the iterable only when some specific event occurs.
For example, Let us take a scenario in which we have a list of 100 elements. We continually ask the user to input a number and whenever they enter an even number, we print the next element of the list.
Now, this cannot be done using a for loop as we cannot predict when the user will enter an even number. Having no order or sequence in the inputs stops us from using the for loop to iterate the list in our program. Iterators can be a handy tool to access the elements of iterables in such situations. So, Let’s learn what an iterator is and how we can create an iterator in python to access the elements of an iterable.
What is an iterator in Python?
An iterator is an object that can be iterated upon. In other words, we can access all the elements in an iterable object using an iterator.
In python, we can create an iterator for any container object using the iter() method. The iter() method takes an iterable object as input and returns an iterator for the same object.
myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
myIter = iter(myList)
print("list is:", myList)
print("Iterator for the list is:", myIter)
Output:
list is: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Iterator for the list is: <list_iterator object at 0x7f4c21734070>
In the output, you can see that a list_iterator object has been created by passing a list to the iter() function.
How to traverse an iterator in Python?
The simplest way to traverse an iterator is by using a for loop. We can access each element in the iterator using a for loop as follows.
myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
myIter = iter(myList)
print("list is:", myList)
print("Elements in the iterator are:")
for element in myIter:
print(element)
Output:
list is: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Elements in the iterator are:
1
2
3
4
5
6
7
8
9
10
As discussed earlier, for loop won’t work if we have no order or sequence for traversing the iterator. For this, we can use two ways.
The first way to access an element of the iterator is by using the __next__() method. The __next__() method, when invoked on the iterator, returns an element next to the previously traversed element. It always retains the information about the element which was returned last time and whenever it is invoked, it returns only the next element which has not been traversed yet. We can understand this using the following example.
myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
myIter = iter(myList)
print("list is:", myList)
print("Elements in the iterator are:")
try:
print(myIter.__next__())
print(myIter.__next__())
print(myIter.__next__())
print(myIter.__next__())
print(myIter.__next__())
print(myIter.__next__())
print(myIter.__next__())
print(myIter.__next__())
print(myIter.__next__())
print(myIter.__next__())
print(myIter.__next__())
print(myIter.__next__())
except StopIteration as e:
print("All elements in the iterator already traversed. Raised exception", e)
Output:
list is: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Elements in the iterator are:
1
2
3
4
5
6
7
8
9
10
All elements in the iterator already traversed. Raised exception
Another way to access the elements of the iterator is by using the next() function. The next() function takes the iterator as input and returns the next element that has not been traversed yet, just like the __next__() method.
myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
myIter = iter(myList)
print("list is:", myList)
print("Elements in the iterator are:")
try:
print(next(myIter))
print(next(myIter))
print(next(myIter))
print(next(myIter))
print(next(myIter))
print(next(myIter))
print(next(myIter))
print(next(myIter))
print(next(myIter))
print(next(myIter))
print(next(myIter))
except StopIteration as e:
print("All elements in the iterator already traversed. Raised exception", e)
Output:
list is: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Elements in the iterator are:
1
2
3
4
5
6
7
8
9
10
All elements in the iterator already traversed. Raised exception
You can observe from the above two examples that the functioning of the __next__() method and next() function are almost similar. Also, both the next() function and the __next__() method raise an StopIteration error when all the elements of the iterator are already traversed. So, it is advised to use exception handling using python try except blocks.
Example use case of an iterator
Now let us take a closer look at the situation discussed above where we have to access the elements from a list only when the user gives an even number as input.
Now, we have the next() function that can access the element from an iterator whenever we call the function. We can use it to access the elements from the list. For this, we will create an iterator for the list and then we will access the elements from the list using the next() function whenever the user gives an even number as input. We can implement a python function for this as follows.
myList = range(0, 101)
myIter = iter(myList)
while True:
try:
user_input = int(input("Input an even number to get an output, 0 to exit:"))
if user_input == 0:
print("Good Bye")
break
elif user_input % 2 == 0:
print("Very good. Here is an output for you.")
print(next(myIter))
else:
print("Input an even number.")
continue
except StopIteration as e:
print("All the output has been exhausted.")
Output:
Input an even number to get an output, 0 to exit:1
Input an even number.
Input an even number to get an output, 0 to exit:2
Very good. Here is an output for you.
0
Input an even number to get an output, 0 to exit:4
Very good. Here is an output for you.
1
Input an even number to get an output, 0 to exit:3
Input an even number.
Input an even number to get an output, 0 to exit:6
Very good. Here is an output for you.
2
Input an even number to get an output, 0 to exit:0
Good Bye
Conclusion
In this article, we have discussed how we can access elements from different iterable objects using an iterator in Python. To learn more about python programming, you can read this article on list comprehension. You may also like this article on the linked list in Python.
Recommended Python Training
Course: Python 3 For Beginners
Over 15 hours of video content with guided instruction for beginners. Learn how to create real world applications and master the basics.