3

现在我正在研究 yield-from 和 await 语法之间的区别。从官方 python 文档中,yield-from generator() 只是以下代码的语法糖:

for i in generator(): yield i

但是我无法在下面的示例中对 yield-from 进行脱糖。

def accumlate():
    # context
    accumlator = 0
    while True:
        next = yield
        if next is None:
            return accumlator
        accumlator += next


def gather(tallies):
    while True:
        tally = yield from accumlate() # (*)
        tallies.append(tally)

def main():
    tallies = []
    accumlator = gather(tallies)
    next(accumlator)
    for i in range(4):
        accumlator.send(i)

    accumlator.send(None)
    for i in range(6, 10):
        accumlator.send(i)
    accumlator.send(None)
    print(tallies)

if __name__ == "__main__":
    main()

我试图用 for-in 版本替换 yield-from,但它不起作用,因为 for-in 不能放在 tally 变量的右侧。用星号标记的代码的确切脱糖是什么?

4

2 回答 2

1

@DerteTrdelnik 的答案在很大程度上是正确的,只是您根本不必修改accumlate函数,因为当生成器返回而没有产生时,生成器已经自动将StopIteration返回值作为参数引发以构造异常对象。

摘自以下文档StopIteration

当生成器或协程函数返回时,StopIteration 会引发一个新实例,并将value函数返回的值用作异常构造函数的值参数。

因此,您只需要gather像这样对函数“脱糖”:

def gather(tallies):
    while True:
        a = accumlate()
        a.send(None)
        while True:
            try:
                a.send((yield))
            except StopIteration as e:
                tallies.append(e.value)
                break
于 2019-09-24T08:16:35.133 回答
0

result = yield from generator()不容易被替换,它是如何获取生成器返回值的方式

https://www.python.org/dev/peps/pep-0380/#proposal

要在不使用 yield from 的情况下模拟一些正在发生的事情,我们必须修改两个生成器

def accumlate():
    # context
    accumlator = 0
    while True:
        next = yield
        if next is None:
            raise StopIteration(accumlator)
        accumlator += next


def gather(tallies):
    internal_acc = accumlate()
    internal_acc.send(None)
    while True:
        try:
            number_to_add = yield
            internal_acc.send(number_to_add)
        except StopIteration as e:
            internal_acc = accumlate()
            internal_acc.send(None)
            tallies.append(e.value)

accumlate不再返回,而是gather加注,除了加注,必须尝试,

用尽后internal_acc,在 except 中创建一个新的

如 pep0380 中所见,还有更多内容,但基本上生成器返回是一个加薪,而产量来自是一个紧凑的捕获

于 2019-09-24T07:32:57.157 回答