9.2 Iterable Objects and the iter() Function in Python

In Python, iterables are objects that can be looped over, or iterated, using a for loop or other iteration mechanisms. An iterable can be a data structure, such as a list, tuple, string, or dictionary, that stores a collection of values. The iter() function is used to obtain an iterator from an iterable, which allows you to access its elements one at a time.

In this section, we will explore what iterable objects are, how the iter() function works, and the difference between iterables and iterators. We will also learn how to create custom iterable objects.


9.2.1 What is an Iterable?

An iterable is an object capable of returning its elements one at a time. In Python, any object that implements the __iter__() method is considered iterable. Common examples of iterables include:

  • Lists: A collection of elements that can be iterated in a specific order.
  • Tuples: Similar to lists but immutable.
  • Strings: A sequence of characters that can be iterated.
  • Dictionaries: A collection of key-value pairs, where keys or values can be iterated.
  • Sets: An unordered collection of unique elements.

Example of Iterables:

# Lists, tuples, and strings are all iterables
my_list = [1, 2, 3]
my_tuple = (4, 5, 6)
my_string = "Python"

# Using a for loop to iterate over them
for item in my_list:
    print(item)

for char in my_string:
    print(char)

In this example:

  • my_list, my_tuple, and my_string are iterable objects. You can use a for loop to iterate over their elements one by one.

9.2.2 The iter() Function

The iter() function is used to convert an iterable into an iterator. An iterator is an object that keeps track of its position during iteration and knows how to return the next element from the iterable using the next() function.

Basic Usage of iter():

# Creating an iterator from a list
my_list = [1, 2, 3]
my_iter = iter(my_list)

# Accessing elements using next()
print(next(my_iter))  # Output: 1
print(next(my_iter))  # Output: 2
print(next(my_iter))  # Output: 3

# Further calls to next() will raise StopIteration
# print(next(my_iter))  # Raises StopIteration

In this example:

  • iter(my_list) returns an iterator for the list.
  • next(my_iter) is used to fetch elements one at a time from the iterator.
  • When there are no more elements, calling next() raises a StopIteration exception.

9.2.3 Iterables vs. Iterators

There is an important distinction between iterables and iterators:

  • Iterable: An object that can return an iterator when passed to the iter() function. Examples include lists, tuples, strings, and dictionaries. An iterable must implement the __iter__() method.
  • Iterator: An object that returns the next item in the sequence when passed to the next() function. An iterator must implement both the __iter__() and __next__() methods.

In simple terms:

  • Iterables produce iterators, which allow you to traverse the elements of an iterable one at a time.

Example of Iterable and Iterator:

my_list = [10, 20, 30]   # Iterable
my_iter = iter(my_list)  # Iterator

# Fetching elements using next()
print(next(my_iter))  # Output: 10
print(next(my_iter))  # Output: 20
print(next(my_iter))  # Output: 30

9.2.4 How Iteration Works with for Loops

When you use a for loop in Python, it implicitly calls the iter() function to obtain an iterator from the iterable, and then calls next() to fetch elements until a StopIteration exception is raised.

Example: for Loop Internally Uses Iterators:

my_list = [1, 2, 3]

# This for loop:
for item in my_list:
    print(item)

# Is equivalent to:
my_iter = iter(my_list)  # Creating an iterator
while True:
    try:
        item = next(my_iter)  # Get the next item
        print(item)
    except StopIteration:
        break  # Stop iteration when no more items

In this example:

  • The for loop is implicitly creating an iterator using iter(my_list) and calling next() internally to fetch elements until it reaches the end of the list.

9.2.5 Creating Custom Iterable Objects

You can create your own iterable objects by defining a class that implements the __iter__() method. This method should return an iterator object that implements the __next__() method.

Example: Custom Iterable Class:

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

    def __iter__(self):
        return MyIterator(self.current, self.end)

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

    def __next__(self):
        if self.current > self.end:
            raise StopIteration  # Stop when the end is reached
        else:
            self.current += 1
            return self.current - 1

# Using the custom iterable
my_iterable = MyIterable(1, 5)
for number in my_iterable:
    print(number)

Output:

1
2
3
4
5

In this example:

  • The MyIterable class implements the __iter__() method, which returns an instance of MyIterator.
  • The MyIterator class implements the __next__() method to control the iteration.
  • The for loop uses this custom iterable to iterate through a range of numbers.

9.2.6 Built-in Iterable Types in Python

Here are some common built-in iterable types in Python:

Sets: An unordered collection of unique elements.

my_set = {1, 2, 3, 4}

Dictionaries: A collection of key-value pairs. Iterating over a dictionary allows you to access its keys, values, or items.

my_dict = {'name': 'Alice', 'age': 25}
for key in my_dict:
    print(key, my_dict[key])

Strings: A sequence of characters.

my_string = "Python"

Tuples: Similar to lists but immutable.

my_tuple = (10, 20, 30)

Lists: Ordered collections of elements.

my_list = [1, 2, 3, 4]

9.2.7 The iter() and next() Functions

The iter() function converts an iterable into an iterator, while the next() function retrieves the next item from an iterator. If no more items are available, next() raises a StopIteration exception.

Example:

my_list = [1, 2, 3]
my_iter = iter(my_list)

# Using next() to fetch elements
print(next(my_iter))  # Output: 1
print(next(my_iter))  # Output: 2
print(next(my_iter))  # Output: 3

# Raises StopIteration if no more items
# print(next(my_iter))  # Raises StopIteration

9.2.8 Summary

  • Iterable objects are objects that can be looped over, such as lists, tuples, strings, dictionaries, and sets. Any object that implements the __iter__() method is iterable.
  • The iter() function converts an iterable into an iterator, which can then be used to retrieve elements one at a time using the next() function.
  • Iterators are objects that implement both the __iter__() and __next__() methods. They track their position during iteration and raise a StopIteration exception when no more elements are available.
  • Python’s for loop automatically creates an iterator and uses the next() function internally to iterate over iterable objects.
  • You can create custom iterable objects by defining a class that implements the __iter__() method and returns an iterator.
  • Common built-in iterables include lists, tuples, strings, dictionaries, and sets.

Understanding iterable objects and the iter() function allows you

to take advantage of Python's powerful iteration capabilities, enabling you to write more efficient and flexible code when working with collections of data.