生成器之理解生成器|老男孩Python培训机构

    /    2019-05-21

理解生成器

定义生成器 

yield关键字,可以让我们定义一个生成器函数。

def generator_func():
    print('a')
    yield 1
g = generator_func()
print(g)
>>> <generator object generator_func at 0x10e178b88>

推动生成器

使用next函数从生成器中取值

def generator_func():
    print('a')
    yield 1
g = generator_func()
ret1 = next(g)
print(ret1)
>>>
a

使用next可以推动生成器的执行,下面的代码,我们可以看到每一次执行next可以让generator_func中代码从上一个位置开始继续执行到yield,并且将yield后面值返回到函数外部,最终我们可以执行到yield 3。

def generator_func():
    print('a')
    yield 1
    print('b')
    yield 2
    print('c')
    yield 3
    print('d')
g = generator_func()
ret1 = next(g)
print(ret1)
ret2 = next(g)
print(ret2)
ret3 = next(g)
print(ret3)
>>>
  a
  b
  c

当函数中已经没有更多的yield时继续执行next(g),遇到StopIteration

def generator_func():
    print('a')
    yield 1
    print('b')
    yield 2
    print('c')
    yield 3
    print('d')
g = generator_func()
ret1 = next(g)
print(ret1)
ret2 = next(g)
print(ret2)
ret3 = next(g)
print(ret3)
next(g)
next和StopIteration

send向生成器中发送数据。send的作用相当于next,只是在驱动生成器继续执行的同时还可以向生成器中传递数据。

import numbers
def cal_sum():
    sum_num = 0
    while True:
        num = yield
        if isinstance(num,numbers.Integral):
            sum_num += num
            print('sum :',sum_num)
        elif num is None:
            break
g = cal_sum()
g.send(None)   # 相当于next(g),预激活生成器
g.send(31)
g.send(25)
g.send(17)
g.send(8)
>>>
sum : 31
sum : 56
sum : 73
sum : 81

生成器中的return和StopIteration

import numbers
def cal_sum():
    sum_num = 0
    while True:
        num = yield
        if isinstance(num,numbers.Integral):
            sum_num += num
            print('sum :',sum_num)
        elif num is None:
            break
    return sum_num
g = cal_sum()
g.send(None)   # 相当于next(g),预激活生成器
g.send(31)
g.send(25)
g.send(17)
g.send(8)
g.send(None)   # 停止生成器
>>>
sum : 31
sum : 56
sum : 73
sum : 81
Traceback (most recent call last):
  File "/Users/jingliyang/PycharmProjects/python的进阶/manager.py", line 19in 
    g.send(None)
StopIteration: 81

import numbers
def cal_sum():
    sum_num = 0
    while True:
        num = yield
        if isinstance(num,numbers.Integral):
            sum_num += num
            print('sum :',sum_num)
        elif num is None:
            break
    return sum_num
g = cal_sum()
g.send(None)   # 相当于next(g),预激活生成器
g.send(31)
g.send(25)
g.send(17)
g.send(8)
try:
    g.send(None)   # 停止生成器
except StopIteration as e:
    print(e.value)
异常处理以及获取return的值

生成器的close和throw

使用throw向生成器中抛一个异常

def throw_test():
    print('a')
    yield 1
    print('b')
    yield 2
g = throw_test()
next(g)
g.throw(Exception,'value error')
>>>
a
Traceback (most recent call last):
File "/Users/jingliyang/PycharmProjects/python的进阶/manager.py", line 32in <module>
g.throw(ValueError,'value error')  # throw和send、next相同,都是驱动生成器继续执行,只不过throw用来向生成器中抛一个异常
File "/Users/jingliyang/PycharmProjects/python的进阶/manager.py", line 26in throw_test
yield 1
ValueError: value error
def throw_test():
    print('a')
    try:
        yield 1
    except ValueError:
        pass
    print('b')
    yield 2
g = throw_test()
next(g)
ret = g.throw(ValueError,'value error')  # throw和send、next相同,都是驱动生成器继续执行,只不过throw用来向生成器中抛一个异常
print(ret)
>>>
a
b
throw+异常处理

使用close关闭一个生成器

def throw_test():
    print('a')
    yield 1
    print('b')
    yield 2
g = throw_test()
ret1 = next(g)
print(ret1)
g.close()
next(g)
>>>
a
Traceback (most recent call last):
  File "/Users/jingliyang/PycharmProjects/python的进阶/manager.py", line 45in <module>
    next(g)
StopIteration


(0)

分享至