主要内容:

  • 小目标:掌握生成器函数
  • 主要内容:yield关键字使用

如果看完这篇文章,你还是弄不明白yield,
你来找我,我保证不打你,我给你发100的大红包。

1. 一个需求

想要产生一个无穷的可迭代对象,每次生成一个随机数;
问题:使用while循环,存放到列表中,内存有限,不可行

2. yield关键字

生成器函数:python中带yield关键字函数,成为生成器函数
一个例子:

import random 
def genRandom():
    #yield关键字
    yield random.randint(0,1000)

#genRandom的返回值不是None,
#genfunc是一个:generator,生成器
genfunc = genRandom()
print(type(genfunc))
#genfunc使用next调用,返回产生的随机数
r = next(genfunc)
print(r)

结果:


803

分析:genfunc为生成器对象;

3 生成器函数调用分析

加入调试信息,观察生成器函数执行过程

import random 
def genRandom():
    #yield关键字
    r = random.randint(0,1000)
    print('befor yield')
    yield r
    print('after yield')
genfunc = genRandom()
  • 第一次调用:
    print(next(genfunc))

    结果:没有执行:print('after yield')

    befor yield
    726

    分析:调用yield之后,返回产生随机数:314,然后停止

  • 再次执行:
    print(next(genfunc))

    结果:

    after yield
    StopIteration  Traceback (most recent call last)

    分析:执行yield下一条语句,并报异常。
    原因:通过异常告知调用者,生成器执行结束;
    如果想要再次执行生成器,必须重新创建生成器对象。

4. 函数中添加多个yield

一个例子:

import random 
def genRandom():
    print('--->1')
    yield random.randint(0,1000)
    print('--->2')
    yield random.randint(0,1000)
    print('--->3')

genfunc = genRandom()
next(genfunc)
next(genfunc)
next(genfunc)

结果:最后一次调用报异常;

--->1
--->2
--->3
StopIteration: 

5. 使用for循环遍历生成器

genfunc = genRandom()
for item in genfunc:
    print(item)

结果:没有问题,因为for循环处理了StopIteration异常

--->1
728
--->2
192
--->3

再次调用:

for item in genfunc:
    print(item)

没有任何结果,

  • 注意:

    1.生成器函数内部yield都执行完之后,不能再次使用;
    2.需要重新创建新的生成器对象

6.无限的生成器函数

代码:

import random 
def genRandom():
    #yield关键字
    while True:
        r = random.randint(0,1000)
        print('befor yield')
        yield r
        print('after yield')

genfunc = genRandom()
for i in range(10):
    print(next(genfunc))
for i in range(10000):
    print(next(genfunc))

结果:可以看到,可以产生无穷尽的随机数

7.yield关键字总结

1.带yield关键字的函数,返回生成器对象;
2.yield关键字保存程序运行上下文
3.生成器可以通过for或者next进行调用,注意异常处理;
4.生成器对象执行完,需要重新创建生成器对象