1

Let's say I have the following code in F#:

let rec all_numbers_from k =
  yield k
  yield! all_numbers_from (k+1)

This code can be called as all_numbers_from 0, generating all numbers from 0 to infinity. I know Python also has a yield keyword, that seems to behave very much like F#'s yield operator. My question is if there's also some sort of equivalent to F#'s yield! operator?

halfer
  • 19,824
  • 17
  • 99
  • 186
devoured elysium
  • 101,373
  • 131
  • 340
  • 557
  • 4
    It might help if you explain what F# `yield!` does. Taking a shot in the dark here: are you looking for [`yield from`](https://stackoverflow.com/questions/9708902/in-practice-what-are-the-main-uses-for-the-new-yield-from-syntax-in-python-3)? – Jonathon Reinhart Jan 05 '20 at 15:56
  • @JonathonReinhart: it can be inferred from the above snippet, but I'll explain: `yield` returns a value, `yield! X` is roughly equivalent to doing an iteration over `X`, yielding all its values (lazily, of course). – devoured elysium Jan 05 '20 at 15:57
  • 2
    Yeah, looks like `yield from`. – Robert Harvey Jan 05 '20 at 15:57
  • 1
    https://docs.python.org/3/whatsnew/3.3.html#pep-380 – Robert Harvey Jan 05 '20 at 15:58
  • @devouredelysium There's [an edit button](https://stackoverflow.com/posts/59601574/edit) you can use to add the explanation to your actual post. – glennsl Jan 05 '20 at 16:49

2 Answers2

5

While yield from is the construct you are looking for, defining this function (co)recursively is horribly inefficient in Python. Use iteration

def all_numbers_from(k):
    while True:
        yield k
        k = k + 1

or just use itertools.count(k).

chepner
  • 497,756
  • 71
  • 530
  • 681
4

The equivalent Python feature would be yield from.

def all_numbers_from(k):
  yield k
  yield from all_numbers_from(k+1)

However this would create a large number of chained generators, and is a poor implementation in Python. See chepner's answer for a better alternative.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328