Million annual salary python road - day12 - Generator

1. Generator # essentially iterators

1.1 generator are built

There are three ways in python to create a generator:

1. function generator

2. Generator derivations

Built-in functions or module 3.python

1.2 generator function

We first examine the building generated by generator function.

def func():
    print(11)
    return 22

ret = func()
print(ret)
# 运行结果:
11
22

The function of the return into the yield, so that it is not func function, but rather a function generator

def func():
    print(11)
    yield 22

We did not write any changes, which is why? Let's see what the function name in parentheses is acquired?

def func():
    print(11)
    yield 22
    
ret = func()
print(ret)

# 运行结果:
<generator object func at 0x000001A575163888>

When we call the function of the function body code will be executed when the execution of the keyword yield, and found that we want to declare a builder. Builder program will give us a return

Builder essentially iterators . How iterator values, how to value generator. Therefore, we can perform direct Next () or ** _ _ next _ _ () ** generators the following method

def func():
     print("111")
     yield 222
    
gener = func() # 这个时候函数不会执⾏. 而是获取到生成器
ret = next(gener) # 这个时候函数才会执行  推荐使用next()
#ret = gener.__next__() # 这个时候函数才会执行
print(ret)  # 并且yield会将func生产出来的数据 222 给了 ret。  

结果:
111
222

And my generator function can be written in more yield.

def func():
    print(11)
    yield 22
    print(33)
    yield 44
    
print(func().__next__())    #启动了一个生成器
print(func().__next__())    #启动了另一个生成器

# 运行结果:
11
22
11
22
def func():
    print("111")
    yield 222
    print("333")
    yield 444

gener = func()
ret = gener.__next__()
print(ret)
ret2 = gener.__next__()
print(ret2)
ret3 = gener.__next__()
# 最后⼀个yield执⾏完毕. 再次__next__()程序报错   StopIteration异常
print(ret3)

When the program is running the last of yield, it continues to run behind the Next () program will be given, corresponding to a yield a next, next exceed the number of yield, it will error, like iterators.

yield and return the difference:

In general the return function is provided only one, his role is to terminate the function, and to the return value of the function's execution.

yield the generator function may be provided in a plurality, and that he does not terminate function, next will yield the corresponding acquisition element generates.

Scenario:

We look at this demand: the old boy selling steamed buns downstairs boss ordered 10,000 buns Baozi Pu boss is very real, they would all worked out. 

def eat():
    lst = []
    for i in range(1,10000):
        lst.append('包子'+str(i))
    return lst

e = eat()
print(e)

Doing so is no problem, but we did not because the students so much, eat about 2000, and the rest of 8000, we can only accomplish some space, put aside. If Baozi Pu boss efficiency is high enough, I eat a bun, a bun you do, then it will not take up too much storage space, and perfect.

def eat():
    for i in range(1,10000):
        yield '包子'+str(i)

e = eat()
for i in range(200):
    next(e)

This difference between the two:

The first is to do it directly to the buns of all, take up memory.

The second is to eat a produce a very memory-saving, but also preserves previous position.

def eat():
    for i in range(1,10000):
        yield '包子'+str(i)

e = eat()
for i in range(200):
    next(e)
for i in range(300):
    next(e)
# 多次next包子的号码是按照顺序记录的。

1.3 send method (understand)

Next we come to a new understanding of things, send method

# next只能获取yield生成的值,但是不能传递值。
def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield
        print(f'{name} start to eat {food}')

g = gen('alex')
next(g)
next(g)
next(g)


# 而使用send这个方法是可以的。
def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield 222
        print(f'{name} start to eat {food}')

g = gen('alex')
next(g)  # 第一次必须用next让指针停留在第一个yield后面
# 与next一样,可以获取到yield的值
ret = g.send('骨头')
print(ret)

结果:
alex ready to eat
alex start to eat 骨头
222


def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield
        print(f'{name} start to eat {food}')

g = gen('alex')
next(g)
# 还可以给上一个yield发送值
g.send('骨头')
g.send('狗粮')
g.send('香肠')

send and next () the difference:

Same point:

send and next () so that the generator can yield a corresponding downward once.

Yield value can be obtained is generated.

difference:

The first acquisition yield values ​​can only be used next can not send (can send (None)).

can send to yield a set value is transmitted.

1.4 yield from

To provide a direct each iteration of a data object may be in the python3 be returned as a result the generator

# 对比yield 与 yield from 
def func():
    lst = ['卫龙','老冰棍','北冰洋','牛羊配']
    yield lst
g = func()
print(g)
print(next(g))  # 只是返回一个列表

结果:
<generator object func at 0x0000018C18AB94F8>
['卫龙', '老冰棍', '北冰洋', '牛羊配']

def func():
    lst = ['卫龙','老冰棍','北冰洋','牛羊配']
    yield from lst
g = func()
print(g)
# 他会将这个可迭代对象(列表)的每个元素当成迭代器的每个结果进行返回。
print(next(g))
print(next(g))
print(next(g))
print(next(g))

结果:
<generator object func at 0x00000213E7D194F8>
卫龙
老冰棍
北冰洋
牛羊配

'''
yield from ['卫龙','老冰棍','北冰洋','牛羊配'] 
等同于:
    yield '卫龙'
    yield '老冰棍'
    yield '北冰洋'
    yield '牛羊配'

1.5 yield from pits

def func():
    lst1 = ['卫龙', '老冰棍', '北冰洋', '牛羊配']
    lst2 = ['馒头', '花卷', '豆包', '大饼']
    yield from lst1
    yield from lst2


g = func()
for i in g:
    print(i)
    
结果:
卫龙
老冰棍
北冰洋
牛羊配
馒头
花卷
豆包
大饼
Returns the result after all of the elements of the first list returned in the second list return

2.

Guess you like

Origin www.cnblogs.com/zhangchaoyin/p/11221236.html