Python生成器send、next、yield from详细解读

生成器:生成器是一类特殊的迭代器,就是需要在生成的时候才产生结果yield,而不是立即返回结果return。这样可以同时节省CPU和内存。

生成器自动实现了迭代器的两个方法:__iter__() 和 __next__()

有两种方法实现生成器:

  1. 生成器函数。使用yield返回结果。yield语句一次返回一个结果,在每个结果中间挂起函数的状态,下次调用时从他离开的地方继续执行。
  2. 生成器表达式。类似列表表达式,用()来表示。

1. 简单的生成器实例

如下代码定义了MyGenerator函数,for循环3次,yield返回值。

gen = MyGenerator() 创建生成器对象gen,但此时MyGenerator函数方法体并没有开始执行。

gen,__next__()激活生成器,打印generator start,并返回for循环第一次遍历的值:0

next(gen)和gen.__next__()作用是一样的,不过此时函数要从for第二次循环开始,不会打印generator start,而是输出值:1

gen.send(None),这个方法跟前面两个方法的作用也是一样的,send()方法传参为None时仅代表激活生成器(执行一次生成器的方法体),第三次输出:2

第四次会发生异常StopIteration,此异常用于标识迭代的完成,因为for循环只循环了3次,迭代结束,

def MyGenerator():
    print("generator start")
    for i in range(3):
        yield i


gen = MyGenerator()
print(gen)             # <generator object MyGenerator at 0xffffa7271900>
print(type(gen))       # <class 'generator'>
print(gen.__next__())  # 打印generator start, 打印 1
print(next(gen))       # 打印 2
print(gen.send(None))  # 打印 3
print(gen.__next__())  # 发生异常 StopIteration

输出:

<generator object MyGenerator at 0xffffa7271900>
<class 'generator'>
generator start
0
1
2
Traceback (most recent call last):
  File "E:\code\test.py", line 10, in <module>
    print(gen.__next__())
StopIteration

2. 生成器对象的send()方法实例

上个实例说明了gen.send(None)参数为空时,仅仅表示激活生成器,调用了生成器函数方法体。

当send()参数不为空时,该参数指定的是上一次被挂起的yield语句的返回值

如下代码:

1. gen.send(None)激活生成器,打印generator start,代码执行到value = yield 666时,会返回666,并挂起

2.gen.send(888),给上一次挂起的yield设置返回值,则vaule=888,代码执行到value2 = yield value,打印:888,然后挂起

3.gen.send(999),给上一次挂起的yield设置返回值,则vaule2=999,代码执行到yield value,打印:999,然后挂起

4.gen.send(000),由于上次挂起的地方是程序的最后一段代码,且没可迭代的对象,则发生异常StopIteration,迭代结束。

def MyGenerator():
    print("generator start")
    value = yield 666
    value2 = yield value
    yield value2

gen = MyGenerator()
print(gen.send(None))  # 激活生成器,打印:generator start,打印:666
print(gen.send(888))  # 给上一次挂起的yield设置返回值,则vaule=888,打印:888
print(gen.send(999))  # 给上一次挂起的yield设置返回值,则vaule2=999 打印:999
print(gen.send(000))  # 迭代结束,发生异常StopIteration

输出:

generator start
666
888
999
Traceback (most recent call last):
File "E:\code\h_test.py", line 11, in <module>
    print(gen.send(000))  # 迭代结束,发生异常StopIteration
StopIteration

3. yield from语法详解

yield from需要在方法体中使用,后面跟着的是可迭代对象,可以是迭代器、生成器。用来遍历输出值。

如下代码:创建了两个迭代对象和两个生成器,使用yield from来遍历它们的值

_list = ["a", "b", "c"]             # 可迭代的列表
_dict = {"name": "zs", "age": 18}   # 可迭代的字典
generator1 = (i for i in range(3))  # 生成器

# 生成器
def generator2():
    for i in range(3, 6):
        yield i

# 遍历输出单个迭代对象的值,该方法也是一个生成器
def func(iter_obj):
    yield from iter_obj

# 遍历输出多个迭代对象的值,该方法也是一个生成器
def func2(*args, **kwargs):
    for item in args:
        yield from item


print(list(func(_list)))  # 输出 a b c

print(list(func2(_list, _dict, generator1, generator2())))

输出:

['a', 'b', 'c']
['a', 'b', 'c', 'name', 'age', 0, 1, 2, 3, 4, 5]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大帅不是我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值