Я пытаюсь понять, как используется 'yield from'. Для этого я написал простую (довольно бесполезную)
пример (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
Я не понимаю, почему "в то время как истина" необходима. Я не знаю другого пути
изменить образец, чтобы он работал.
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 (Нет) без 'while True' в proxy2 вызывает StopIteration. Я модифицировал
Proxy2:
def proxy2(cnt):
tmp = yield from counter2()
cnt.update(tmp)
yield
Опять же, я не вижу объяснения этому, но это работает.
Обновление 04/05
Я экспериментировал и изучал документы. Ниже (ИМХО) приведен код, который мне кажется правильным. Я удалил лишний «yield» из прокси2.
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. Я не могу сказать, что нашел там подтверждение кода выше.