Python3 Iterators and Generators


Iterator

Iteration is one of Python's most powerful features, and a way to access collection elements.

An iterator is an object that can remember the position of the traversal.

The iterator object starts accessing from the first element of the collection until all elements have been accessed. Iterators can only go forward, not backward.

Iterators have two basic methods:iter()andnext()。

Strings, lists, or tuple objects can all be used to create iterators:

Example (Python 3.0+)

>>> list=[1,2,3,4]
>>> it = iter(list)    # Create an iterator object
>>> print (next(it))   # Output the next element of the iterator
1
>>> print (next(it))
2
>>>

Iterator objects can be traversed using a regular for statement:

Example (Python 3.0+)

#!/usr/bin/python3 list=[1,2,3,4] it = iter(list) # Create an iterator object for x in it: print (x, end=" ")

Executing the above program produces the following output:

1 2 3 4

You can also use the next() function:

Example (Python 3.0+)

#!/usr/bin/python3 import sys # Import the sys module list=[1,2,3,4] it = iter(list) # Create an iterator object while True: try: print (next(it)) except StopIteration: sys.exit()

Executing the above program produces the following output:

1
2
3
4

Create an Iterator

To use a class as an iterator, you need to implement two methods in the class: __iter__() and __next__().

If you already understand object-oriented programming, you know that classes have a constructor. Python's constructor is __init__(), which is executed when the object is initialized.

For more information, refer to:Python3 Object-Oriented Programming

The __iter__() method returns a special iterator object that implements the __next__() method and signals the completion of the iteration through a StopIteration exception.

The __next__() method (next() in Python 2) returns the next iterator object.

Create an iterator that returns numbers, starting with an initial value of 1 and incrementing by 1 each step:

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))

The output after execution is:

1
2
3
4
5

StopIteration

The StopIteration exception is used to signal the completion of the iteration and prevent infinite loops. In the __next__() method, we can set it to raise the StopIteration exception after completing a specified number of loops to end the iteration.

Stop execution 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)

The output after execution is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Generator

In Python, functions that use `yield`yieldare called generators (generator).

yield`yield` is a keyword used to define generator functions. A generator function is a special kind of function that can produce values step by step during iteration, rather than returning all results at once.

Unlike ordinary functions, a generator is a function that returns an iterator and can only be used for iteration operations. To put it simply, a generator is an iterator.

When using `yield` in a generator functionyieldstatement, the execution of the function pauses, andyieldthe expression after `yield` is returned as the value of the current iteration.

Then, every time the generator'snext()`__next__()` method is called orfor`for` loop is used for iteration, the function resumes execution from where it was last paused until it encounters anotheryield`yield` statement. In this way, the generator function can produce values step by step, without needing to compute and return all results at once.

Calling a generator function returns an iterator object.

The following is a simple example that demonstrates the use of generator functions:

Example

def countdown(n): while n > 0: yield n n -= 1 # Create a generator object generator = countdown(5) # Get values by iterating over the generator print(next(generator)) # Output: 5 print(next(generator)) # Output: 4 print(next(generator)) # Output: 3 # Use a for loop to iterate over the generator for value in generator: print(value) # Output: 2 1

In the above example,countdownthe function is a generator function. It uses yield statements to gradually produce countdown numbers from n to 1. Each time a yield statement is executed, the function returns the current countdown value and, on the next call, continues execution from where it was last paused.

By creating a generator object and using the next() function or a for loop to iterate over the generator, we can gradually obtain the values produced by the generator function. In this example, we first use the next() function to get the first three countdown values, then use a for loop to get the remaining two.

The advantage of generator functions is that they can produce values on demand, avoiding generating a large amount of data at once and occupying a large amount of memory. In addition, generators can work seamlessly with other iteration tools (such as for loops), providing a concise and efficient iteration method.

Executing the above program produces the following output:

5
4
3
2
1

The following example uses yield to implement the Fibonacci sequence:

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 and generated by the generator while True: try: print (next(f), end=" ") except StopIteration: sys.exit()

Executing the above program produces the following output:

0 1 1 2 3 5 8 13 21 34 55
Other Extensions