Deep understanding of generators in Python
Generator concept
The generator does not save the results in a series, but saves the state of the generator and returns a value each time it iterates until it encounters a StopIteration exception.
Generator syntax
Generator expression: The same as the list parsing syntax, but replace the [] of list parsing with ()
The things that generator expressions can do can basically be handled by list parsing, but when it needs to be processed When the sequence is relatively large, list parsing consumes more memory.
>>> gen = (x**2 for x in range(5))
>>> gen
>>> for g in gen:
... print(g, end='-')
...
0-1-4-9-16-
>>> for x in [0,1,2 ,3,4,5]:
... print(x, end='-')
...
0-1-2-3-4-5-
Generator function: In the function if If the yield keyword appears, then the function is no longer an ordinary function, but a generator function.
But the generator function can produce an unlimited sequence, so the list cannot be processed at all. The function of
yield is to turn a function into a generator. A function with yield is no longer an ordinary function, and the Python interpreter will treat it as a generator.
The following is a generator function that can produce odd numbers infinitely.
def odd():
n=1
while True:
n+=2
odd_num = odd()
count = 0
for o in odd_num:
if count >=5: break
print( o)
Count +=1
def __init__(self):
self.start=-1
DEF __iter __ (Self):
Return Self __next __ (Self):
Self.start += 2
Return Self.start
i = it ()
For Count in Range (5):
Print (NExt (i) )
Digression: The generator contains __iter() and next__() methods, so you can directly use for to iterate, but self-written Iter that does not include StopIteration can only iterate through manual loops. isinstance(odd_num, Iterator)
>>> from collections import Iterator
>>> isinstance(odd_num, Iterator) )True
>>> iter(odd_num) is odd_num
True
>>> help(odd_num)
Help on generator object:
odd = class generator(object)
| Methods defined here:
|
| __iter__(self, /)
| Implement iter(self).
|
| __next__(self, /)
| As a result, now you can loop according to the Iterator method with confidence!
When the for loop is executed, each loop will execute the code inside the fab function. When it reaches yield b, the fab function returns an iteration value. In the next iteration, the code continues to execute from the next statement of yield b, and The function's local variables look exactly the same as before the last interruption, so the function continues execution until yield is encountered again. It looks like a function is interrupted several times by yield during normal execution, and each interruption returns the current iteration value through yield.
yield and return
In a generator, if there is no return, StopIteration will be returned when the function is completed by default;
... yield 1
...>>> g=g1()
>>> next(g) #When next(g) is called for the first time, it will hang after executing the yield statement, so the program does not Execution ends.1
>>> next(g) #The program tries to start execution from the next statement of the yield statement and finds that it has reached the end, so it throws a StopIteration exception.Traceback (most recent call last):
File "StopIteration
>>>
If return is encountered, if return is during execution, Then throw StopIteration directly to terminate the iteration.
>>> def g2():
... yield 'a'
... return
... yield 'b'
...
>>> g=g2()
>>> next(g) #The program stays at the position after executing the yield 'a' statement.
'a'
>>> next(g) #The program finds that the next statement is return, so a StopIteration exception is thrown, so that the yield 'b' statement will never be executed.
Traceback (most recent call last):
File "
StopIteration
If a value is returned after return, then this value is a description of the StopIteration exception, not a program The return value.
The generator has no way to use return to return a value.
>>> def g3():
... yield 'hello'
... return 'world'
...
>>> g=g3()
>> > next(g)
'hello'
>>> next(g)
Traceback (most recent call last):
File "
StopIteration: world
Methods supported by generator
>>> help(odd_num)
Help on generator object:
odd = class generator(object)
| Methods defined here:
......
| close(...)
| close() -> raise GeneratorExit inside generator.
|
| send(...)
| send(arg) -> send 'arg' into generator,
| return next yielded value or raise StopIteration.
|
| throw(...)
| throw(typ[,val[,tb]]) -> raise exception in generator,
| return next yielded value or raise StopIteration.
. .....
close()
Manually close the generator function, and subsequent calls will directly return the StopIteration exception.
>>> def g4():
... yield 1
... yield 2
... yield 3
...
>>> g=g4()
> >> next(g)
1
>>> g.close()
>>> next(g) #After closing, the yield 2 and yield 3 statements will no longer work
Traceback ( most recent call last):
File "
StopIteration
send()
The biggest feature of the generator function is that it can accept a variable passed in from the outside, and The result is calculated based on the variable content and returned.
This is the most difficult part to understand about the generator function, and it is also the most important part. The implementation of the coroutine I will talk about later depends on it.
def gen():
value=0
while True:
receive=yield value
if receive=='e':
break
value = 'got: %s' % receive
g=gen()
print(g.send(None))
print(g.send('aaa'))
print(g.send(3))
print(g.send('e'))
Execution process:
The generator function can be started through g.send(None) or next(g) and executed to the end of the first yield statement.
At this time, the yield statement has been executed, but the receive has not been assigned a value.
yield value will output the initial value 0
Note: You can only send(None) when starting the generator function. If you try to enter other values, you will get an error message.
Through g.send('aaa'), aaa will be passed in and assigned to receive. Then the value of value will be calculated and returned to the while head. The execution of the yield value statement will stop.
At this time, the yield value will output "got: aaa" and then hang.
Through g.send(3), step 2 will be repeated, and the final output result is "got: 3"
When we g.send('e'), the program will execute break and then exit the loop, and finally The entire function is executed, so you will get a StopIteration exception.
The final execution result is as follows:
0
got: aaa
got: 3
Traceback (most recent call last):
File "h.py", line 14, in
print(g.send( 'e'))
StopIteration
throw()
is used to send an exception to the generator function, which can end system-defined exceptions or custom exceptions.
Throw() directly throws an exception and ends the program, or consumes a yield, or proceeds directly to the end of the program when there is no next yield.
WHILE TRUE:
Try:
yield 'normal value'
yield' normal value 2'
print ('hee')
Except Valueerror:
Print ('We Got Valueerror Heres ') X Except Typeerror ; The result is:
normal value
we got ValueError here
normal value
normal value 2
Traceback (most recent call last):
File "h.py", line 15, in
print(g.throw (TypeError))
StopIteration
Explanation:
print(next(g)): will output normal value and stay before yield 'normal value 2'.
Since g.throw(ValueError) is executed, all subsequent try statements will be skipped, which means that yield 'normal value 2' will not be executed, and then enter the except statement and print out we got ValueError here.
Then enter the while statement part again and consume a yield, so the normal value will be output.
print(next(g)) will execute the yield 'normal value 2' statement and stay at the position after executing the statement.
g.throw(TypeError): will jump out of the try statement, so print('here') will not be executed, and then execute the break statement, jump out of the while loop, and then reach the end of the program, so a StopIteration exception will be thrown.
The following is a comprehensive example to expand a multi-dimensional list, or flatten a multi-dimensional list)
try:
#If it is a string, manually throw TypeError. An If isInstance (Nested, Str):
for Sublist in Nested:
#YIELD FLATTEN (SUBLIST)
#Yield Element
Print ('GOT : ', Element)Except TypeError:
#print('here') yield nested
L=['aaadf',[1,2,3],2,4,[5,[6,[8,[9]],'ddf '],7]]
for num in flatten(L):
print(num)
If it is a bit difficult to understand, then it will be clearer to open the comment of the print statement and check it. The function generated by
yield from
yield is an iterator, so we usually put it in a loop statement to output the result.
Sometimes we need to put the iterator generated by this yield in another generator function, that is, generator nesting.
For example, the following example:
def inner():
for i in range(10):
yield i
def outer():
while True:
res = g_Inner.Send (None)yield res
g_outer = OUTER ()
While True:
Print (g_outer.Send (None))
Break
At this time, we can use yield from g. statement to reduce our workload.
def outer2():
Yield from inner()
Of course, the focus of the yield from statement is to help us automatically handle exceptions between the inner and outer layers. There are 2 well-written articles here, so I will No more nagging.
http://blog.theerrorlog.com/yield-from-in-python-3.html
http://stackoverflow.com/questions/9708902/in-practice-what-are-the-main-uses-for -the-new-yield-from-syntax-in-python-3
Summary
According to the duck model theory, the generator is a kind of iterator, which can be iterated using for.
When next(generator) is executed again, it will be executed from the suspended state.
The loop ends when it encounters the end of the program or encounters StopIteration.
You can pass in parameters through generator.send(arg), which is the coroutine model.
You can manually close the generator through generator.close().
next() is equivalent to send(None)
The above is the in-depth understanding of generators in Python. For more related articles, please pay attention to the PHP Chinese website (www.php.cn)!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

PHP is mainly procedural programming, but also supports object-oriented programming (OOP); Python supports a variety of paradigms, including OOP, functional and procedural programming. PHP is suitable for web development, and Python is suitable for a variety of applications such as data analysis and machine learning.

PHP is suitable for web development and rapid prototyping, and Python is suitable for data science and machine learning. 1.PHP is used for dynamic web development, with simple syntax and suitable for rapid development. 2. Python has concise syntax, is suitable for multiple fields, and has a strong library ecosystem.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

PHP originated in 1994 and was developed by RasmusLerdorf. It was originally used to track website visitors and gradually evolved into a server-side scripting language and was widely used in web development. Python was developed by Guidovan Rossum in the late 1980s and was first released in 1991. It emphasizes code readability and simplicity, and is suitable for scientific computing, data analysis and other fields.

VS Code can run on Windows 8, but the experience may not be great. First make sure the system has been updated to the latest patch, then download the VS Code installation package that matches the system architecture and install it as prompted. After installation, be aware that some extensions may be incompatible with Windows 8 and need to look for alternative extensions or use newer Windows systems in a virtual machine. Install the necessary extensions to check whether they work properly. Although VS Code is feasible on Windows 8, it is recommended to upgrade to a newer Windows system for a better development experience and security.

VS Code can be used to write Python and provides many features that make it an ideal tool for developing Python applications. It allows users to: install Python extensions to get functions such as code completion, syntax highlighting, and debugging. Use the debugger to track code step by step, find and fix errors. Integrate Git for version control. Use code formatting tools to maintain code consistency. Use the Linting tool to spot potential problems ahead of time.

Running Python code in Notepad requires the Python executable and NppExec plug-in to be installed. After installing Python and adding PATH to it, configure the command "python" and the parameter "{CURRENT_DIRECTORY}{FILE_NAME}" in the NppExec plug-in to run Python code in Notepad through the shortcut key "F6".

In VS Code, you can run the program in the terminal through the following steps: Prepare the code and open the integrated terminal to ensure that the code directory is consistent with the terminal working directory. Select the run command according to the programming language (such as Python's python your_file_name.py) to check whether it runs successfully and resolve errors. Use the debugger to improve debugging efficiency.
