- What is the generator?
- Return vs yield?
- Examples
- yield & yield from
- In addition to yield, generator objects can make use of the following methods:
- Generator expression
- Generator expression vs list comprehension
- Generator chains
- *All the ways to call generator
- Creating a generator
- Consuming it
- References
What is the generator?
‣
next(), it resumes where it left off. You mostly use loop inside generator func.Return vs yield?
- The difference is that while a
returnstatement terminates a function entirely,yieldstatement pauses the function saving all its states and later continues from there on successive calls.
Examples
def my_range(start, end):
current = start
while current < end:
yield current
current += 1
for num in my_range(1, 10): # range(1, 10)
print(num)
# OR
nums = my_range(1, 10)
next(nums)
next(nums)‣
‣
‣
yield & yield from
yield from g is equivalent to for v in g: yield v
Useful for creating coroutines (handles StopIteration automatically.
yield from is a transparent two way channelbetween the caller and the sub-generator.
In addition to yield, generator objects can make use of the following methods:
.send()- sends data to a generator.throw()- to raise generator exceptions.close()- to stop a generator’s iteration
‣
‣
yield fromGenerator expression
# Initialize the list
my_list = [1, 3, 6, 10]
# square each term using list comprehension
list_ = [x**2 for x in my_list]
# same thing can be done using a generator expression
# generator expressions are surrounded by parenthesis ()
generator = (x**2 for x in my_list)
print(list_)
print(generator)
[1, 9, 36, 100]
<generator object <genexpr> at 0x7f5d4eb4bf50>Generator expression vs list comprehension
- Generator expressions generate values “just in time”, while LC executed everything at once.
‣
Generator chains
- Used for data processing pipelines.
‣
*All the ways to call generator
Here's the full set, split into how you create one and how you consume it.
Creating a generator
def gen(): # generator function
yield 1
yield 2
g = gen() # calling it returns a generator object, runs nothing yet
squares = (x*x for x in range(5)) # generator expressionConsuming it
One item at a time
next(g) # preferred
next(g, None) # with default instead of StopIteration
g.__next__() # what next() calls under the hoodIterating
for x in g: ...
while True:
try:
x = next(g)
except StopIteration:
breakDraining into a container
list(g), tuple(g), set(g), dict(g), frozenset(g)Unpacking
a, b, c = g # must match length exactly
first, *rest = g
[*g], {*g}, (*g,) # star-unpack into a literal
f(*g) # spread as function argumentsFunctions that eat an iterable
sum(g), max(g), min(g), any(g), all(g), sorted(g), len(list(g))
"".join(g)
zip(g, other), map(f, g), enumerate(g), filter(f, g)
itertools.islice(g, 3) # partial consumption, stays lazyTwo-way communication (coroutine style)
g.send(None) # equivalent to next(g); required to prime
g.send(value) # value becomes the result of the paused `yield`
g.throw(ValueError) # raise an exception at the paused yield
g.close() # raise GeneratorExit inside, run cleanupDelegation from another generator
def outer():
result = yield from gen() # forwards next/send/throw, captures return valueDiscarding everything fast
collections.deque(g, maxlen=0) # C-speed exhaust with no memoryThe one gotcha across all of these: a generator is single-pass. Once exhausted, every further call gives StopIteration — you have to build a new one.
References
- https://www.youtube.com/watch?v=tmeKsb2Fras
- https://www.integralist.co.uk/posts/python-generators/#generators
- https://www.programiz.com/python-programming/generator
- https://realpython.com/introduction-to-python-generators/
- http://www.dabeaz.com/coroutines/
- https://www.bogotobogo.com/python/python_function_with_generator_send_method_yield_keyword_iterator_next.php
- https://stackoverflow.com/questions/19892204/send-method-using-generator-still-trying-to-understand-the-send-method-and-quir
- https://www.nbshare.io/notebook/286849692/Python-Generators/
- https://stackoverflow.com/questions/9708902/in-practice-what-are-the-main-uses-for-the-yield-from-syntax-in-python-3-3