Python practical notes (10) advanced features - generator

With list comprehensions, we can directly create a list. However, due to memory constraints, the list capacity is definitely limited. Moreover, creating a list with 1 million elements not only takes up a lot of storage space, but if we only need to access the first few elements, then most of the space occupied by the latter elements will be wasted.

So, if the elements of the list can be calculated according to a certain algorithm, can we continue to calculate the subsequent elements in the process of looping? This saves a lot of space by not having to create a complete list. In Python, this mechanism of computing while looping is called a generator: generator.

>>> L = [x * x for x in range(10)]
>>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10))

As we said, the generator saves the algorithm. Each time it is called next(g), it calculates the gvalue of the next element, until the last element is calculated, and StopIterationan error is thrown when there are no more elements.
Generators are also iterables:

>>> g = (x * x for x in range(10))
>>> for n in g: ... print(n) ... 0 1 4 9 16 25 36 49 64 81 

If the calculation algorithm is complex and forcannot be implemented by a loop similar to list generation, it can also be implemented by a function.

For example, in the famous Fibonacci sequence, any number except the first and second numbers can be obtained by adding the first two numbers:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

The Fibonacci sequence cannot be written with list comprehension, but it is easy to print it with a function:

def fib(max):
    n, a, b = 0, 0, 1 while n < max: print(b) a, b = b, a + b n = n + 1 return 'done' 

The above functions and generators are just one step away. To turn fiba function into a generator, just print(b)change yield bit to:

def fib(max):
    n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 return 'done' 

This is another way to define a generator. If a function definition contains yieldkeywords, then the function is no longer a normal function, but a generator

Here, the most difficult thing to understand is that the execution flow of generator and function is different. Functions are executed sequentially, returnreturning when a statement or the last line of a function statement is encountered. The function that becomes the generator is next()executed every time it is called, and the statement is returned when it encounters yielda statement, and it continues to execute from the last returned yieldstatement when it is executed again.

As a simple example, define a generator that returns the numbers 1, 3, and 5 in turn:

def odd():
    print('step 1') yield 1 print('step 2') yield(3) print('step 3') yield(5) 

When calling the generator, first generate a generator object, and then use the next()function to continuously get the next return value:

>>> o = odd()
>>> next(o)
step 1
1
>>> next(o)
step 2 3 >>> next(o) step 3 5 >>> next(o) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration 

It can be seen that oddit is not an ordinary function, but a generator. During the execution process, it yieldwill be interrupted when it encounters it, and the execution will continue next time. After executing 3 times yield, there is no yieldmore to execute, so the fourth call next(o)will report an error.

Similarly, after changing the function to a generator, we basically never use it next()to get the next return value, but directly use the forloop to iterate:

>>> for n in fib(6):
... print(n) ... 1 1 2 3 5 8 

But forwhen the generator is called with a loop, it is found that the return value of the generator's returnstatement cannot be obtained. If you want to get the return value, you must catch the StopIterationerror, and the return value is contained StopIterationin value:

>>> g = fib(6)
>>> while True: ... try: ... x = next(g) ... print('g:', x) ... except StopIteration as e: ... print('Generator return value:', e.value) ... break ... g: 1 g: 1 g: 2 g: 3 g: 5 g: 8 Generator return value: done 

About how to catch errors, the error handling will be explained in detail later.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325734318&siteId=291194637