跳转至

Python-:生成器

yield

yield是一个很有意思的语法糖,如果在一个函数中有yield,那么这个函数就不再是一个函数了,它将返回一个生成器对象

  • 生成器是通过函数实现的迭代器
  • 在下次调用__next__()之后,生成器开始执行yield之后的语句
  • yield 能指定生成某个函数的计算结果
  • 包含yield的语句都是生成器
  • 迭代器在取完所有的值之后,再次取值会报异常

Demo

def set_yield(lst):#定义生成器函数
    for i in lst:#循环遍历参数列表
        if i %3 ==0:#判断是否符合条件
            yield i#根据生成器返回计算结果
a = set_yield([1,2,3,4,5,6,7,8,9,9,12,123,145,12456])
while True:
    try:
        print(next(a))  #通过内置函数逐一输出 因为是WhileTrue所以会无限取 会出错被下方捕捉
    except:
        break  #捕捉异常进行输出结束
print(next(a)) #这里报错了 迭代器已经取完值了会报错 所以上方才会有异常捕捉 StopIteration

生成器推导式

a = (i for i in range(100) if i %3 !=0)
print(next(a))
print(list(a))  #  让剩余的作为列表打印出来

throw:异常

  • 迭代过程中用户手动引发异常
def l_list(lst):
    try:
        for i in lst:
            if i % 3 == 0:
                yield i
    except:
        raise Exception('终止了')
a = [96,19,29,72,16,3,45,6,7,9,15,10]
s = l_list(a)
print(next(s))
s.throw(Exception)

close:关闭

  • close()用于手动关闭生成器,关闭之后无法手动再生成
def l_list(lst):
    for i in lst:
        if i %3 ==0:
            yield i
a = [96,19,29,72,16,3,45,6,7,9,15,10]
s = l_list(a)
print(next(s))
print(next(s))
s.close() #这里进行手动关闭
print(next(a)) #这里已经关闭了 TypeError: 'list' object is not an iterator

send

  • 不能直接用需要迭代器最少迭代一次 才能使用.因为send()是取回前一次的生成结果!
def a():
    print('aaa')
    p1 = yield '123'
    print('bbb')
    if (p1 == 'hello'):
        print('p1是send传过来的')
    p2= yield '234'
    print(p2)
r = a()
next(r)
r.send('hello')
#print(next(r))
'''        首先 a是一个生成器 生成一个迭代器r  执行到next(r)的时候进入迭代器内部执行第一句print('aaa')语句
        然后执行p1 = yield '123' 迭代跳出 执行r.send('hello')并且把'hello'传入进去赋值给p1
        继续向下执行输出'bbb'  向下执行进行判断成立执行输出'p1是send传过来的',
'''

小技巧

  • 通过yield 只能向下取值 来取出无限层的列表并生成可迭代对象(列表中的列表嵌套次数来决定递归的次数)
def list_str_yield(lst):
    for i in lst:
        try:
            try:               #如果是字符串就可以加空白字符不会出错则直接执行else语句不会进行拆分了,直接返回一整个
                i+''
            except:            #如果不能相加会报错直接pass  执行下面的for循环进行递归
                pass
            else:              #字符串到这里应引发一个异常 被外界捕获
                raise Exception
            for d in list_str_yield(i):
                yield d
        except:
            yield i
c = [1,2,123,1,[123,4,51,[123,'abc',3,[1,7],45,51,[123,'abc',3,[1,7],45,35,],35,],51,[123,'abc',3,[1,7],45,35,],1235,123,[1234,],123]]
a = list_str_yield(c)
print(list(a))