python advanced-generator (17)

1. What is an integrator?

We can create lists directly by using the Formula of Lists. However, due to memory constraints, the list capacity must be limited. Moreover, creating a list of 1 million elements not only takes up a lot of storage space, but if we only need to access the previous one, then most of the elements are wasted. So, if the list elements can be deduced according to some algorithm, can we continue to deduce the following elements in the process of the cycle? This eliminates the need to create a complete list, saving space from \\\\\\\. In Python, this mechanism of edge-cycling edge-computing is called generator.

 

2. Establishment of

There are many ways to create a complete device. The first method is very simple, as long as the [] formula of the list is changed to ()

List Generator

L = [2*x for x in range(1,10)]
print(L)

The results are as follows:[2, 4, 6, 8, 10, 12, 14, 16, 18]

generator

G = (2*x for x in range(1,10))
p

The results are as follows: <generator object < genexpr > at 0x00000111152FC408 >

The difference between creating L and G is only in the outermost [] and (), where L is a list and G is an integrator. We can print every element of L directly, but how do we print every element of G? If you want to print out one of them, you can get the next of them by the next() function.

G = (2*x for x in range(1,10))
print(G)
print(next(G))
print(next(G))
print(next(G))
print(next(G))
print(next(G))
print(next(G))

The results are as follows: 2, 4, 6, 8, 10, 12.

G = (2*x for x in range(1,10))
print(G)
print(next(G))
print(next(G))
print(next(G))
print(next(G))
print(next(G))
print(next(G))
print(next(G))
print(next(G))
print(next(G))
print(next(G))

The results are as follows:

<generator object <genexpr> at 0x0000022CCCC8C408>
2
4
6
8
10
12
14
16
18
Traceback (most recent call last):
  File "C:\Users\Se7eN_HOU\Desktop\A.py", line 12, in <module>
    print(next(G))
StopIteration

Be careful:

  • Every time G is adjusted, the value of the next element of G is calculated until the last element is calculated. When there are no more elements, the StopIteration exception is thrown.
  • Of course, this constant next() is too perverted. The correct method is to make for loop, because integrator is also an iterative object. So, when we create a adult, we basically never tune next(), iterates through a for loop, and we don't need to turn off the StopIteration exception.

 

3. Establishment of generator method 2

generator is always strong. If the arithmetic of calculation is complex, function can be used to implement the for loop method similar to list.

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

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

The Formula of Fibolacci Sequence List can't be written, but it's easy for the function to print it out.

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

fib(5)

The operation results are as follows: 1, 1, 2, 3, 5

Looking carefully, we can see that fib function actually defines the inference rules of Fibolacci sequence. It can start with the first element and infer the following arbitrary elements. This logic is often similar.
Generator. That is to say, the functions and generators of the above are only a step away. To turn the fib function into a generator, you just need to change print(b) to yield b:

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

f = fib(5)
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))

The results are as follows:

1
1
2
3
5
Traceback (most recent call last):
  File "C:\Users\Se7eN_HOU\Desktop\demo.py", line 16, in <module>
    print(next(f))
StopIteration: done

In the case of fib, if we constantly adjust yield during the cycle, it will be interrupted. Of course, it is necessary to set a condition for the cycle to exit the cycle, otherwise the production limit will be listed. Similarly, after changing the function to generator, we basically never get the next next() to get the next return value, which is directly iterated by the for loop:

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

for n in fib(5):
    print(n)

The results are as follows:

1
1
2
3
5

However, when the for loop calls generator, it is found that the return value of the generator's return statement cannot be obtained. If you want to get the return value, you must catch the StopIteration error, which is included in the value of StopIteration:

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

f = fib(5)
while True:
    try:
        x = next(f)
        print("value=%d"%x)
    except StopIteration as e:
        print("Generator return value=%s"%e.value)
        break

The results are as follows:

value=1
value=1
value=2
value=3
value=5
Generator return value = done

 

4. The _next_() method is the same as next().

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

f = fib(5)
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())

The results are as follows:

1Traceback (most recent call last):

1
2
3
5
  File "C:\Users\Se7eN_HOU\Desktop\demo.py", line 16, in <module>
    print(f.__next__())
StopIteration: done

 

5.,send()

def fib(times):
    n=0
    a,b = 0,1
    while n<times:
        temp = yield b
        print(temp)
        a,b = b,a+b
        n+=1

f = fib(5)
print(f.__next__())
print(f.send("Se7eN_HOU"))
print(f.send("Se7eN"))
print(next(f))
print(f.__next__())

The results are:

1
Se7eN_HOU
1
Se7eN
2
None
3
None
5

From the example above, we can see that the send () function can pass parameters to the generator when it generates objects.

summary

  • An adult is a function that remembers the position in the body of the function on the last return. In the middle of the function, all the local variables of the last function remain unchanged.
  • An adult not only "remembers" its data state, but also "remembers" its position in a flow control construct (which in imperative programming is not just a data value).

The characteristics of the integrator:

  • 1. Save memory
  • 2. When iterating to the next adjustment, all the parameters are reserved by the first adjustment, that is to say, all the parameters of the function are reserved by the second adjustment, and they are not newly created.

Keywords: Python Programming

Added by irishmike2004 on Wed, 15 May 2019 23:09:25 +0300