生成器 yield from

简介

yield from 是在Python3.3才出现的语法。所以这个特性在Python2中是没有的

yield from 后面需要加的是可迭代对象,它可以是普通的可迭代对象,也可以是迭代器,甚至是生成器。

使用

astr='ABC'
alist=[1,2,3]
adict={"name":"wangbm","age":18}

agen=(i for i in range(4,8)) # 生成器

def gen(*args, **kw):
    for item in args:
        yield from item

new_list=gen(astr, alist, adict, agen)
print(list(new_list))
['A', 'B', 'C', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 1, 2, 3, 'name', 'age', 4, 5, 6, 7]

Process finished with exit code 0

yield from后面加上可迭代对象,他可以把可迭代对象里的每个元素一个一个的yield出来,对比yield来说代码更加简洁,结构更加清晰。

复杂应用:生成器的嵌套

yield from 后面加上一个生成器后,就实现了生成的嵌套。

使用yield from可以让我们避免让我们自己处理各种料想不到的异常,而让我们专注于业务代码的实现

概念

  • 调用方:调用委派生成器的客户端(调用方)代码
  • 委托生成器:包含yield from表达式的生成器函数
  • 子生成器:yield from后面加的生成器函数
# 子生成器
def average_gen():
    total = 0
    count = 0
    average = 0
    while True:
        new_num = yield average
        count += 1
        total += new_num
        average = total/count

# 委托生成器
def proxy_gen():
    while True:
        yield from average_gen()

# 调用方
def main():
    calc_average = proxy_gen()
    next(calc_average)            # 预激下生成器
    print(calc_average.send(10))  # 打印:10.0
    print(calc_average.send(20))  # 打印:15.0
    print(calc_average.send(30))  # 打印:20.0

if __name__ == '__main__':
    main()
10.0
15.0
20.0
计算完毕!!
总共传入 3 个数值, 总和:60,平均数:20.0

Process finished with exit code 0

委托生成器的作用是:在调用方与子生成器之间建立一双向通道

双向通道是什么?
调用方可以通过send()直接发送消息给子生成器,而子生成器yield的值,也是直接返回给调用方。

委托生成器,只起一个桥梁作用,它建立的是一个双向通道,它并没有权利也没有办法,对子生成器yield回来的内容做拦截。

处理异常

yield from帮我们做了很多的异常处理,而且全面,而这些如果我们要自己去实现的话,一个是编写代码难度增加,写出来的代码可读性极差,这些我们就不说了,最主要的是很可能有遗漏,只要哪个异常没考虑到,都有可能导致程序崩溃什么的。

你可能感兴趣的:(日积跬步)