13.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)

  • 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

13.1.1. Plain Function

  • Plain function returns plain object

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

13.1.2. Generator Function

  • Generator function returns generator object

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

13.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

13.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

13.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)