首页 > 解决方案 > 为什么'yield from'需要一个封闭的'while 1'?

问题描述

我试图了解如何使用“收益”。为此,我编写了一个简单(相当无用)的示例(count_vowels.py),运行时会在下面生成:

$ python3 count_vowels.py 
Counter({'a': 5})

请解释为什么 proxy2 函数(委托生成器)中需要“while True”?

没有'while True':

$ python3 count_vowels.py 
Traceback (most recent call last):
  File "count_vowels.py", line 39, in <module>
    main()
  File "count_vowels.py", line 34, in main
    p.send(None)
StopIteration

我不明白为什么需要'while True'。我知道没有其他方法可以修改示例以使其工作。

count_vowels.py

from collections import Counter

VOWELS = 'AEIOU'


def counter2():
    cnt2 = Counter()
    while True:
        c = yield
        if c is None:
            break
        if str.upper(c) in VOWELS:
            cnt2[c] += 1
    return cnt2


def proxy2(cnt):
    while True:  # w/o this while I get 'StopIteration' exception
        tmp = yield from counter2()
        cnt.update(tmp)


def main():
    word = 'abracadabra'
    cnt = Counter()
    p = proxy2(cnt)
    next(p)
    for c in word:
        p.send(c)
    p.send(None)
    print(cnt)


if __name__ == '__main__':
    main()

使用 Python3.5.3,Debian GNU/Linux 9.8(拉伸)

更新:Windows7,Python 3.7.2,同样的结果。

更新:05/04 p.send(None) 在 proxy2 中没有“while True”会引发 StopIteration。我修改了proxy2:

def proxy2(cnt):
    tmp = yield from counter2()
    cnt.update(tmp)
    yield

同样,我没有看到任何解释,但它有效。

更新 04/05

我一直在试验和研究文档。下面(恕我直言)是我看起来正确的代码。我从 proxy2 中删除了多余的“收益”。

def counter2(cnt):
    while True:
        c = yield
        if c is None:
            break
        if isinstance(c, (str)) and (str.upper(c) in VOWELS):
            cnt[c] += 1
    return cnt


def proxy2(cnt):
    tmp = yield from counter2(cnt)
    return tmp


def main():
    word = 'abracadabra'
    cnt = Counter()
    p = proxy2(cnt)
    next(p)
    for c in word:
        p.send(c)
    try:
        p.send(None)
    except StopIteration as exc:
        res = exc.value
    print(res)

我一直在研究 PEP 380。我不能说我在那里找到了上面代码的确认。

标签: debianpython-3.5yield-from

解决方案


推荐阅读