Почему эта рекурсивная функция `` `yield from``` не вызывает ошибку? - PullRequest
0 голосов
/ 19 апреля 2020
def prefixes(s):
    if s:
        yield from prefixes(s[:-1])
        yield s

t = prefixes('both')
next(t)

Следующее (t) возвращает 'b'. Я просто не понимаю, почему это так, потому что если мы выполним оператор yield from, мы в конечном итоге закончим на yield from prefixes(''), что вернет None. Во всех других моих тестах выход из None вызывает ошибку TypeError. Вместо этого это, кажется, просто игнорируется, и префиксы ('b') переходят к следующему оператору yield («зачем он это делает?»), Чтобы получить «b» ... Есть идеи, почему? Буду очень признателен за объяснение.

Ответы [ 2 ]

0 голосов
/ 19 апреля 2020

prefixes обернуто в генераторе, который вызывает StopIteration, когда функция возвращается. Когда передается пустая строка, prefixes пропускает любые выходы, достигает конца своего блока кода и возвращает, вызывая StopIteration. Возвращаемое значение не имеет значения, оно отбрасывается

>>> next(prefixes(""))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

yield from, подавляет StopIteration внутреннего генератора и позволяет внешнему генератору продолжать работу.

0 голосов
/ 19 апреля 2020

генераторы - это ленивые (по требованию) объекты, вы не исчерпали свой генератор t, чтобы исчерпать свой генератор, вы можете использовать:

list(t)
# ['b', 'bo', 'bot', 'both']

теперь, если вы используете next(t), вы будете получить ожидаемое StopIteration

StopIteration                             Traceback (most recent call last)
<ipython-input-25-680ef78477e2> in <module>
      6 t = prefixes('both')
      7 list(t)
----> 8 next(t)

StopIteration: 

утверждение if "гарантирует", что у вас есть конец, и вы никогда не сделаете None[:-1], чтобы получить TypeError

...