The
generator is essentially an iterator, but it is special.
Take the list container as an example. When using the container to iterate a set of data, you must store all the data in the container before you can start the iteration; but the generator is different. It can generate elements while iterating.
In other words, for multiple data that can be calculated using an algorithm, the generator does not generate them all at once, but when and when they are needed.
Not only that, the creation of generators is much simpler than iterators, which are roughly divided into the following 2 steps:
Define a function that identifies the return value with the yield keyword;
You can create a
generator by calling the function you just created.
for example:
def intNum():
print("Start execution")
for i in range(5):
yield i
print("Continue execution")
num = intNum()
From this, we successfully created a num generator object. Obviously, unlike ordinary functions, the return value of the number() function uses the yield keyword instead of the return keyword, and such functions become generator functions.
Compared with return, yield not only can return the corresponding value, but also has a more important function, that is, whenever the program finishes executing the statement, the program will be suspended. Not only that, even if the generator function is called, the Python interpreter will not execute the code in the function, it will only return a
generator (object).
There are two ways to execute the generator function, or to continue the execution of the program immediately suspended after the yield statement is executed:
Call the next() built-in function or __next__() method through the generator (num in the above program);
Iterate through the generator with a for loop.
For example, on the basis of the above program, add the following statement:
#Call next() built-in function
print(next(num))
#Call the __next__() method
print(num.__next__())
#Traversing the generator through a for loop
for i in num:
print(i)
The program execution result is:
start execution
0
Continue to execute
1
Continue to execute
2
Continue to execute
3
Continue to execute
4
Continue to execute
Here it is necessary to analyze the execution flow of a program for the reader:
1) First, under the premise of creating a num generator, calling the next() built-in function through it will cause the Python interpreter to start executing the code in the intNum() generator function, so it will output "start execution" and the program will It executes until yield i, and at this time i==0, so the Python interpreter outputs "0". Due to the effect of yield, the program will pause here.
2) Then, we use the num generator to call the __next__() method, which has the same effect as the next() function (in fact, the bottom layer of the next() function also executes the __next__() method), it will be The program continues to execute, that is, "continue to execute" is output, and the program will execute to yield i. At this time, i==1, so "1" is output, and then the program is suspended.
3) Finally, we use the for loop to traverse the num generator. The reason why we can do this is because the bottom of the for loop will continuously call the next() function to continue the suspended program, so it will output the subsequent results.
Note that in the Python 2.x version, the __next__() method cannot be used. The next() built-in function can be used. In addition, the generator has the next() method (that is, called by num.next()).
In addition, you can also use the list() function and tuple() function to directly store all the values that the generator can generate as a list or tuple. E.g:
num = intNum()
print(list(num))
num = intNum()
print(tuple(num))
The program execution result is:
start execution
Continue to execute
Continue to execute
Continue to execute
Continue to execute
Continue to execute
[0, 1, 2, 3, 4]
start execution
Continue to execute
Continue to execute
Continue to execute
Continue to execute
Continue to execute
(0, 1, 2, 3, 4)
It can be judged from the output results that the underlying implementation of list() and tuple() is similar to the traversal process of for loop.
Compared with the iterator, the most obvious advantage of the generator is to save memory space, that is, it does not generate all the data at once, but when and when it is needed.