Iterators
Iteration is one of Python's most powerful features, offering a way to access the elements of a collection.
An iterator is an object that remembers its position during traversal.
It begins by accessing the first element of the collection and moves forward until all elements are visited. Iterators can only move in one direction—forward.
Two basic methods define an iterator: iter()
and next()
.
Strings, lists, or tuple objects can be used to create an iterator:
Example (Python 3.0+)
>>> my_list = [1, 2, 3, 4] >>> it = iter(my_list) # Creating an iterator object >>> print(next(it)) # Output the next iterator element 1 >>> print(next(it)) 2
Iterating with a for
loop
You can also use a for
loop to traverse through an iterator:
Example (Python 3.0+)
#!/usr/bin/python3 my_list = [1, 2, 3, 4] it = iter(my_list) # Creating an iterator object for x in it: print(x, end=" ")
Output:
1 2 3 4
Using next()
You can also manually iterate through items using the next()
function:
Example (Python 3.0+)
#!/usr/bin/python3 import sys # Import sys module my_list = [1, 2, 3, 4] it = iter(my_list) # Creating an iterator object while True: try: print(next(it)) except StopIteration: sys.exit()
Output:
1 2 3 4
Creating an Iterator
To use a class as an iterator, the class needs to implement two methods: __iter__()
and __next__()
.
If you're familiar with object-oriented programming, you know classes have constructors. In Python, the constructor method is __init__()
, which initializes the object when it's created.
The __iter__()
method should return the iterator object itself and must implement the __next__()
method. The __next__()
method returns the next value from the iterator and raises a StopIteration
exception to signal the end of the iteration.
Example: Creating an Iterator Class
The following example creates an iterator that returns numbers starting from 1, increasing by 1:
Example (Python 3.0+)
class MyNumbers: def __iter__(self): self.a = 1 return self def __next__(self): x = self.a self.a += 1 return x myclass = MyNumbers() myiter = iter(myclass) print(next(myiter)) print(next(myiter)) print(next(myiter)) print(next(myiter)) print(next(myiter))
Output:
1 2 3 4 5
StopIteration Exception
The StopIteration
exception signals the end of the iteration and prevents infinite loops. You can set the StopIteration
exception after a certain number of iterations to stop the process.
Example: Stopping After 20 Iterations
Example (Python 3.0+)
class MyNumbers: def __iter__(self): self.a = 1 return self def __next__(self): if self.a <= 20: x = self.a self.a += 1 return x else: raise StopIteration myclass = MyNumbers() myiter = iter(myclass) for x in myiter: print(x)
Output:
1 2 3 ... 19 20
Generators
In Python, a function that uses yield
is called a generator.
The yield
keyword defines a generator function that produces values one at a time during iteration, rather than returning them all at once.
Unlike normal functions, generators return an iterator, which can be used to iterate over the values produced by the generator function.
When the yield
statement is executed, the function's state is "paused," and the expression following yield
is returned as the current iteration's value. When the generator's next()
method is called again or the generator is used in a for
loop, the function resumes execution from where it last left off.
Example: Generator Function
def countdown(n): while n > 0: yield n n -= 1 # Creating a generator object generator = countdown(5) # Getting values from the generator print(next(generator)) # Output: 5 print(next(generator)) # Output: 4 print(next(generator)) # Output: 3 # Iterating through the remaining generator values for value in generator: print(value) # Output: 2 1
The countdown
function in this example is a generator function that yields countdown numbers from n
to 1
. You can retrieve values using next()
or iterate over them with a for
loop.
Generators have the advantage of producing values on demand, rather than computing and storing all values at once.
Fibonacci Sequence Generator
The following example demonstrates the use of yield
to generate Fibonacci numbers:
Example (Python 3.0+)
#!/usr/bin/python3 import sys def fibonacci(n): # Generator function - Fibonacci a, b, counter = 0, 1, 0 while True: if counter > n: return yield a a, b = b, a + b counter += 1 f = fibonacci(10) # f is an iterator, returned by the generator while True: try: print(next(f), end=" ") except StopIteration: sys.exit()
Output:
0 1 1 2 3 5 8 13 21 34 55