python 迭代器、生成器

一、迭代器协议

对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stoplteration 异常,终止迭代(只能往后不能往前退)。

二、for循环提高

for循环中,调用对象__iter__()方法,将其变成遵循迭代器协议的迭代对象,再通过其内部的__next__()方法进行依次访问,从而达到遍历效果。

三、生成器

可以理解为数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己内置的__iter__方法),生成器就是可迭代对象。

运行生成器方法:

  1. 生成器函数  __next__()
  2. python自带方法:next(生成器)
  3. .send(参数):生成器函数.send(参数),send中的参数会传入到当前停止 yield 中。

生成器表现形式:(generatorobject 生成器对象)

  1. 生成器函数:与常规函数定义相同,但是使用yield返回结果,在每个结果中间挂起函数,以使下次从它离开的地方继续执行。
  2. 生成器表达式:类似于列表推导,但是生成器按需产生结果的一个对象,而不是一次构建一个结果列表。
L = [x + 1 for x in range(10)]
print(L)

# 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

基本语法:

def 函数名():
    yield 返回值
    yield 返回值

# yield 特性:与return相同,可以yield多次,可以保存状态。

yield 语句是生成器中的关键语句,生成器在实例化时并不会被执行,而是等待调用其__next__()方法才开始运行。并且当程序运行完yield语句后就会“吼(hold)住”,即保持当前状态且停止运行,等待下一次遍历时才恢复运行,并会把 .send(参数) 中的参数传回到yield。

生成器案例:生产者、消费者模型(吃包子案例)

# 吃包子
def conSumer(name):
    print('我是[%s],准备开始吃包子了!' % name)
    while True:
        baozi = yield
        print('%s 很开心的把 [%s] 吃掉了。' % (name,baozi))


# 生成包子
def producer():
    c1 = conSumer('tt')
    c1.__next__()
    for i in range(10):
        c1.send('包子%s' % i)


producer()

执行结果:

我是[tt],准备开始吃包子了!
tt 很开心的把 [包子0] 吃掉了。
tt 很开心的把 [包子1] 吃掉了。
tt 很开心的把 [包子2] 吃掉了。
tt 很开心的把 [包子3] 吃掉了。
tt 很开心的把 [包子4] 吃掉了。
tt 很开心的把 [包子5] 吃掉了。
tt 很开心的把 [包子6] 吃掉了。
tt 很开心的把 [包子7] 吃掉了。
tt 很开心的把 [包子8] 吃掉了。
tt 很开心的把 [包子9] 吃掉了。

你可能感兴趣的:(python,迭代器,生成器)