Home › Learn › Python › Functions in depth

Generators

Lesson 35 of 40. Produce values one at a time with yield.

A function that uses yield instead of return is a generator. Calling it does not run the body; it returns a generator object that produces one value each time it is asked, pausing at each yield and resuming from there. for x in countdown(3): asks repeatedly; list(gen) collects everything; next(gen) takes one value.

Generators are for sequences that are long, infinite, or expensive to build all at once: reading a huge file line by line, or producing numbers until the caller has enough. They can only be consumed once.

def evens():
    n = 0
    while True:
        yield n
        n += 2

g = evens()
print(next(g), next(g), next(g))   # 0 2 4

Your task

Write countdown(n) as a generator yielding n down to 1, and sentences(text), a generator that yields each sentence of the text: the pieces between ., !, and ? characters, with surrounding whitespace stripped and empty pieces skipped, so "Hi there. Bye!" yields "Hi there" and then "Bye".

Part of the final project. sentences yields the sentences of a text one at a time, for the sentence count. It is saved in this browser and loaded into Project: text statistics when you get there.

Hint 1

while n > 0: yield n; n -= 1

Hint 2

for ch in text: if ch in ".!?": yield current.strip() if it is not empty, then current = ""; else current += ch. After the loop, yield what is left if it is not empty.

Show the solution
def countdown(n):
    while n > 0:
        yield n
        n -= 1


def sentences(text):
    current = ""
    for ch in text:
        if ch in ".!?":
            if current.strip():
                yield current.strip()
            current = ""
        else:
            current += ch
    if current.strip():
        yield current.strip()

    Runs CPython compiled to WebAssembly in this tab (12 MB download the first time, then cached); nothing is sent anywhere.