三、生成器

生成器

利用迭代器,我们可以在每次迭代获取数据(通过next()方法)时按照特定的规律进行生成。但是我们在实现一个迭代器时,关于当前迭代到的状态需要我们自己记录,进而才能根据当前状态生成下一个数据。为了达到记录当前状态,并配合next()函数进行迭代使用,我们可以采用更简便的语法,即生成器(generator)。生成器是一类特殊的迭代器。

2.1 创建生成器的方法1

要创建一个生成器,有很多种方法,第一种方法很简单,只要把一个列表推导式的[]改成()

列表推导式:
l = [i for i in range(1,10) if i % 2 == 0]

生成器:
l = (i for i in range(1,10) if i % 2 == 0)
#生成器是一类特殊的迭代器,所以也可以使用next()函数或者__next__()方法来获取生成器的值
print(next(l))	#2
print(l.__next__())	#4
print(next(l))	#6
print(l.__next__())	#8
#也可以使用for...in来循环该生成器
for i in l:
    print(i,end = ' ')
#2 4 6 8

2.2 创建生成器的方法2

要求:

  • 函数中包含 yield语句

    • yield 可以去阻断当前函数的执行,当使用next()函数,或者使用__next__()方法都会让这个函数继续执行,当执行到下一个 yield语句的时候,又会被暂停
    • 一直到生成器内所有的yield语句都被执行后,再次使用next()函数,或者使用__next__()方法都会让这个函数继续执行时,将后续代码执行完后,会弹出StopIteration异常
  • 直接输出这个函数的结果就是'生成器'<generator object test at 0x03CFBBC0>

yield关键字可以不指定值

def test():
    print('x')
    yield 1
    print('a')

    yield 2
    print('b')

    yield 3
    print('c')

    yield 4
    print('d')
a = test()	#该函数并未被执行,仅仅用于产生一个生成器
print(next(a))	
'''
x
1

yield 可以去阻断当前函数的执行,当使用next()函数,或者使用`__next__()`方法都会让这个函数继续执行,当执行到下一个 yield语句的时候,又会被暂停
'''

print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
'''
x
1
a
2
b
3
c
4
d
StopIteration
'''

2.2.1 send()

  • send()方法有一个参数,指定的是上一次被挂起的yield语句的返回值
  • 相比于__next__()方法,send可以额外的给yield语句传值
  • 注意第一次调用 变量名.send(None)
def zzw():
    res1 = yield 1
    print(res1)
    res2 = yield 2
    print(res2)
a = zzw()
print(next(a))
print(a.send('zhang'))
#此刻 send 既有继续执行函数的功能,还有着将实参作为上一次yield语句的值传递给变量res1的作用

print(a.send('zhang'))
#TypeError: can't send non-None value to a just-started generator
#如果将send作为启动函数来代替next(),那么就不能加入参数,否则会报错。因为不存在上一次yield语句

print(a.send(None))
print(a.send(None))
#send默认参数值为None,即如果使用send方法不填入实参,那么输出结果会报错
print(a.send())
#TypeError: generator.send() takes exactly one argument (0 given)
posted @ 2021-06-02 09:44  zzwYYYYYY  阅读(61)  评论(0)    收藏  举报