yield 与 yield from

def parent():
    t = son()
    print(type(t))
    result = t.send(None) # 开始迭代
    print(result)
    result = t.send(20)
    print(result)
    result = t.send(None) #引发StopIteration
def son():
    n = 1
    m = 1
    while True:
        y = yield m
        if y is None:
            raise StopIteration
        else:
            m += y
#试想下如果单次处理一次嵌套,还可以接受,但是如果多次进行嵌套进行与子生成器进行通讯,
#都要进行获取值,发送值,异常处理,正确的退出, 显得会很麻烦
#引用官方的解释
# Python生成器是协程的一种形式,但具有限制,它只能屈服于其直接调用者。这意味着包含yield的一段代码不能被分解出来并以与其他代码相同的方式放入单独的函数中
# 执行这样的分解会导致被调用的函数本身成为一个生成器,并且有必要明确地迭代第二个生成器并重新产生它生成的任何值,
# 如果屈服值是唯一关心的问题,那么使用循环(例如)可以毫不费力地执行此操作
# for v in g:
#     yield v
# 然而,如果在调用send(),throw()和close()的情况下,子生成器要与调用者正确交互,事情变得相当困难。正如后面将会看到的那样,
# 必要的代码非常复杂,并且正确处理所有的角落案例是非常棘手的。
# 将提出新的语法来解决这个问题。在最简单的用例中,它将等同于上面的for循环,
# 但它也将处理全部的生成器行为,并允许以简单直接的方式对生成器代码进行重构。
#因此出现了新的形式 yield from
def parent1():
    yield from son()

p = parent1()
result1 = next(p) # 或者用p.send(None)
result1 = p.send(10)
print(result1)
result1 = p.send(None) #引发异常
print(result1)
# 上面的yield from 做体现了几个优点:
# 1 简写了写法,更简洁,
# 2 与子生成器开启了双向通道,既能像子生成器发送值,也能接受值返回到调用者,子生成器的异常也会被传递给调用者
# 3 在多次嵌套中使用起来更简洁,语法更简单

 

posted @ 2018-03-06 09:53  我是外婆  阅读(260)  评论(0编辑  收藏  举报