14.1. Generator About

  • Processes one element at a time

  • Does not remember previous element

  • Does not know next element

  • Can be used only once

  • Save memory (does not require more memory for processing large data)

  • Values are computed on demand

  • No need to store all values in memory

  • Uses around 10% more CPU than regular processing

  • Typical usage: streams, processing larger than memory files or data

  • Cannot use len() as of generators don't have length

  • Previous element is overridden by current on next()

  • Functions (list, dict, tuple, frozenset, set, sum, all, any, etc) will evaluate generator instantly

14.1.1. Plain Function

  • Plain function returns plain object

def run():
    return 1
type(run)
<class 'function'>
type(run())
<class 'int'>

14.1.2. Generator Function

  • Generator function returns generator object

def run():
    yield 1
type(run)
<class 'function'>
type(run())
<class 'generator'>

14.1.3. Yield vs. Return

  • After return function stops

  • After yield function pauses

def run():
    return 1
    return 2
def run():
    yield 1
    yield 2

14.1.4. Lazy Evaluation

  • After yield function pauses

  • Calling next() resumes function until next yield

  • After last yield raises StopIteration

def run():
    yield 1
    yield 2
result = run()
next(result)
1
next(result)
2
next(result)
Traceback (most recent call last):
StopIteration

14.1.5. Instant Evaluation

  • Using list() will evaluate generator instantly

  • Functions (list, tuple, set, dict, sum, min, max, all, any, etc) will evaluate generator instantly

def run():
    yield 1
    yield 2
result = run()
tuple(result)
(1, 2)