The python generator (Generator)

It does not generate the results stored in a series, but save the state generator, returns a value at each time iteration, until the encounter ends abnormally StopTteration

1, the generator syntax:

  Generator expressions: syntax parsing through the list, but the list comprehension [] replace ()

  Generator expressions can do basic list comprehension can handle, but when the sequence requires relatively large, relatively non-memory list comprehension

2, generator function:
  appears yield keyword in the function, then the function is not in an ordinary function, but function generator

  But the generator function can produce an infinite sequence, so there is no way to process the list

  The role of yield is a function into a generator, with a yield function is no longer an ordinary function, Python interpreter will treat it as a generator

3、yield 与 return

  When a return StopTterration Builder, if there is no return, the function is performed to complete the default

def gen():
    yield 'a'



>>> g = gen()
>>> next(g)
traceback (most recent call last):
    File"<stdin>", line 1, in <module>
StopIterration

  If the return is encountered in the implementation process, the direct termination of the iteration throws StopIteration

Gen DEF ():
     the yield  ' A ' 
    return  
    the yield  ' B '
 
>>> G = Gen ()
 >>> Next (G) stays in the implementation of the program # play yield "a" position of the statement after the 
'A'
 >>> Next (g) # when the program finds the next return statement, so throw StopTieration, so yield 'b' statement is never executed 
Traceback (MOST recent Results Last Call): 
        File " <stdin> " , Line 1 , in <Module> 
StopIteraion

Supported methods generator

1、close()

  Manual closing generator, directly behind the call returns StopIteration exception

>>> DEF Gen ():
     the yield  . 1 
    the yield  2 
    the yield  . 3
 
>>> G = Gen ()
 >>> Next (G)
 . 1 
after >>> g.close () # close the yield  2 and the yield  . 3 statement will not in act 
Traceback (Last Call MOST): 
    File " <stdin> " , Line . 1 , in <Module1> 
the StopIteration

2、send()

  The greatest feature of the function generator is a variable can accept incoming external, variable according to the results returned content

  This is where the generator function difficult to understand, is the most important place, it is thanks to him Ctrip

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

Implementation process:

  1, the initiator can function by g.send (None) or next (g), and executes a first position at the end yield statements

    At this point, execution over the yield statement, but not to receive an assignment, yield value will output initial value 0

  2, by g.send ( 'aaa'), will pass aaa, and assigned to receive, and then calculate the value of value, while the head and back, do yield value statement has stopped

    At this time, the output will yield value '' got 'aaa, and then hangs

  3, g.send through (3), repeat the second step, the final output is "got:" 3

  4, when we g.send ( 'e'), and then break the program execution exits the loop, and finally the entire function is finished, the exception will be StopItration

0
got: aaa
got: 3
Traceback (most recent call last):
File "h.py", line 14, in <module>
  print(g.send('e'))
StopIteration

 

3、throw()

  It is fed to a function generator to the exception and to be system-defined ends abnormally, or custom exception

  throw (after) the end of direct rule out abnormal procedure. A consumed or yield, or directly to the end of the program in the absence of a time yiled

def gen():
    while True: 
        try:
            yield 'normal value'
            yield 'normal value 2'
            print('here')
        except ValueError:
            print('we got ValueError here')
        except TypeError:
            break

g=gen()
print(next(g))
print(g.throw(ValueError))
print(next(g))
print(g.throw(TypeError))

The output is:

normal value
we got ValueError here
normal value
normal value 2
Traceback (most recent call last):
  File "h.py", line 15, in <module>
    print(g.throw(TypeError))
StopIteration

Implementation process:

  1, print (next (g)): outputs Normal value, and remain in the yield 'normal value' before

  2, due to the implementation of g.throw (TypeError), it will try to skip all subsequent statement, that "yield 'normal value2'" will not be executed, the statement except to let enter, print out we got ValueError here

    Then re-enter the while loop part, consumed a yield, it will output normal value

  3, print (next (g)), will perform yield normal value2 statement, and the rest position after the hi-line statement below

  4, g.throw (TypeError): try statement will jump out, so print ( 'here') will not be carried out of the while loop, then to the end of the program, so raise StopIteration

 

Comprehensive example, the list expands a multi-dimensional, multi-dimensional or flat list

def flatten(nested):
    
    try:
        #如果是字符串,那么手动抛出TypeError。
        if isinstance(nested, str):
            raise TypeError
        for sublist in nested:
            #yield flatten(sublist)
            for element in 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)

  

4、yield from

  yield is a function of generating an iterator, the us it will usually be placed in the loop output, sometimes we need to produce this iterator yield in a function generator, the generator is nested.

The following example:

def inner():
    for i in range(10):
        yield i
def outer():
    g_inner=inner()    #这是一个生成器
    while True:
        res = g_inner.send(None)
        yield res

g_outer=outer()
while True:
    try:
        print(g_outer.send(None))
    except StopIteration:
        break

There are two very good article written by:

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

to sum up

  1, in accordance with the duck model theory, the iterator is a kind of generator, may be used for loop iteration

  2, the first execution next (generator), will be executed after completion of the yield statement suspends program, all the parameters and the state saved

    Once again, when executed next (generator), will start from the next execution suspended state

  In the face of the end of the program or StopIteration, ending cycle

  3, by generator. send (arg); parameters passed in this model is coroutine

  4, by generator. throw (exception) to pass an exception, throw statement will consume a yield

    By generator. close () Close the generator manually

  5, next () equivalent to send (None)

 

Guess you like

Origin www.cnblogs.com/jcjc/p/11423468.html