[python basics] understand iterators and generators

1. Iterator

1.1 use of iterators

The iterator object is accessed from the first element of the collection until all the elements are accessed. Iterators can only move forward, not backward. Iterators have two basic methods: iter() and next(). String, list, or tuple objects can be used to create iterators.

  • iter(iterable): an iterator that returns iteratable objects.
  • next(iterator): get the next record from the iterator. If the next record cannot be obtained, a StopIteration exception is triggered
  • Examples of using iter and next
lst = [1,2,3,4]
it = iter(lst) #Create iterator object
print(it) # <list_iterator object at 0x7fb8e443ed30>
print(next(it)) # 1
print(next(it)) # 2
  • for recycling example:
lst = [1,2,3,4]
it = iter(lst) #Create iterator object
for x in it:
    print(x, end=" ") # 1 2 3 4 

You can also use next instead of the above example:

import sys  # Introducing sys module

lst = [1, 2, 3, 4]
it = iter(lst)  # Create iterator object

while True:
    try:
        print(next(it))
    except StopIteration:
        sys.exit()

Output:

1
2
3
4

1.2 creating iterators for classes

Using a class as an iterator requires two methods to be implemented in the class__ iter__ () and__ next__ () .

class MyNumbers:
    def __iter__(self):
        self.a = 1
        return self

    def __next__(self):
        if self.a <= 10: #Number of iterations, otherwise the for loop will always execute
            x = self.a
            self.a += 1
            return x
        else:
            raise StopIteration


myclass = MyNumbers()
myiter = iter(myclass) 

for x in myiter: #You can also use object directly here, because its class has already defined iter and next.
    print(x,end = " ") # 1 2 3 4 5 6 7 8 9 10

2. Generator

2.1 use of generator

In Python, functions that use yield are called generators. Different from ordinary functions, a generator is a function that returns an iterator and can only be used for iterative operations. It is easier to understand that a generator is an iterator.

Simple use examples of generator:

def func(n):
    yield n*2

f = func(5)
print(f) # <generator object func at 0x7f36613ad308>
print(next(f)) # 10. Value of iterator
print(next(f)) # report errors!!! Because this function returns only one iterator

For ease of understanding, yield can be regarded as a return operation. The difference is that the code behind yield will continue to be executed the next time the function is called. Therefore, when a yield operation is encountered, you first need to return the value of the iterator instead of immediately executing the code behind yield. When the function is called next time, you will continue to perform the operation that was not completed last time. Obviously, using the generator is simpler than the iterator, and the performance is as efficient. Let's take another example to illustrate.

def fib(n):
    pre,curr = 0,1
    while n > 0:
        n-=1
        yield curr
        pre,curr = curr,curr+pre
        print("I am a generator!")

for i in fib(5):
    print(i)
    print("-----------------------")

Output:

1
-----------------------
I am a generator!
1
-----------------------
I am a generator!
2
-----------------------
I am a generator!
3
-----------------------
I am a generator!
5
-----------------------
I am a generator!

When using the for loop operation, it traverses 5 times, and the last time it will call StopIteration, so it will output "I am a generator!" 5 times. However, if next is used, it will be different because it will not automatically call the next function, as shown in the following example:

def func(n):
    yield n*2
    print("I am a generator!")

f = func(5)
print(f) # <generator object func at 0x7f36613ad308>
print(next(f)) # 10. Value of iterator

The output result is:

<generator object func at 0x7fd74460b308>
10

You can see that the program behind yield will not be executed because the function is not called again!

2.2 generator expression

The generator expression is very similar to the list derivation. The only difference is that one uses a comprehensive sign and the other uses parentheses. The generator expression returns the generator object, while the list derivation returns the list object.

g = (i*2 for i in range(10))
print(type(g)) # <class 'generator'>

for i in g:
    print(i,end=" ") # 0 2 4 6 8 10 12 14 16 18 

Tags: Python

Posted on Sun, 28 Nov 2021 15:20:13 -0500 by lizlazloz