Skip to main content
minor improvements in clarity, links, naming
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
def squares_listsquare_list(n):
    the_list = []                         # Replace
    for x in range(n):
        y = x * x
        the_list.append(y)                # these
    return the_list                       # lines
def squares_the_yield_waysquare_yield(n):
    for x in range(n):
        y = x * x
        yield y                           # with this one.

yield is a sugarysugary way to say

>>> for square in squares_listsquare_list(4):
...     print(square)
...
0
1
4
9
>>> for square in squares_the_yield_waysquare_yield(4):
...     print(square)
...
0
1
4
9

Yield is single-pass: you can only iterate through once. When a function has a yield in it we call it a generator function. And an iterator is what it returns. That'sThose terms are revealing. We lose the convenience of a container, but gain the power of ana series that's computed as needed, and arbitrarily long series.

Yield is lazy, it puts off computation. A function with a yield in it doesn't actually execute at all when you call it. when you call it. The iterator object itIt returns usesan magic to maintain the function's internal contextiterator object that remembers where it left off. Each time you call next() on the iterator (this happens in a for-loop) execution inches forward to the next yield. (return raises StopIterationStopIteration and ends the series. (this is the natural end of a for-loop).

Yield is versatile. Data doesn't have to be stored all together, it can be made available one at a time. It can dobe infinite loops:.

>>> list(squares_the_yield_waysquare_yield(4))
[0, 1, 4, 9]
def squares_list(n):
    the_list = []                         # Replace
    for x in range(n):
        y = x * x
        the_list.append(y)                # these
    return the_list                       # lines
def squares_the_yield_way(n):
    for x in range(n):
        y = x * x
        yield y                           # with this one.

yield is a sugary way to say

>>> for square in squares_list(4):
...     print(square)
...
0
1
4
9
>>> for square in squares_the_yield_way(4):
...     print(square)
...
0
1
4
9

Yield is single-pass: you can only iterate through once. When a function has a yield in it we call it a generator function. And an iterator is what it returns. That's revealing. We lose the convenience of a container, but gain the power of an arbitrarily long series.

Yield is lazy, it puts off computation. A function with a yield in it doesn't actually execute at all when you call it. The iterator object it returns uses magic to maintain the function's internal context. Each time you call next() on the iterator (this happens in a for-loop) execution inches forward to the next yield. (return raises StopIteration and ends the series.)

Yield is versatile. It can do infinite loops:

>>> list(squares_the_yield_way(4))
[0, 1, 4, 9]
def square_list(n):
    the_list = []                         # Replace
    for x in range(n):
        y = x * x
        the_list.append(y)                # these
    return the_list                       # lines
def square_yield(n):
    for x in range(n):
        y = x * x
        yield y                           # with this one.

yield is a sugary way to say

>>> for square in square_list(4):
...     print(square)
...
0
1
4
9
>>> for square in square_yield(4):
...     print(square)
...
0
1
4
9

Yield is single-pass: you can only iterate through once. When a function has a yield in it we call it a generator function. And an iterator is what it returns. Those terms are revealing. We lose the convenience of a container, but gain the power of a series that's computed as needed, and arbitrarily long.

Yield is lazy, it puts off computation. A function with a yield in it doesn't actually execute at all when you call it. It returns an iterator object that remembers where it left off. Each time you call next() on the iterator (this happens in a for-loop) execution inches forward to the next yield. return raises StopIteration and ends the series (this is the natural end of a for-loop).

Yield is versatile. Data doesn't have to be stored all together, it can be made available one at a time. It can be infinite.

>>> list(square_yield(4))
[0, 1, 4, 9]
simpler wording
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105

When you find yourself building a list from scratch...Instead of this:

...yield each piece insteaddo this:

def squares_the_yield_way(n):
    for x in range(n):
        y = x * x
        yield y                           # with this one.

Whenever you find yourself building a list from scratch, yield each piece instead.

When you find yourself building a list from scratch...

...yield each piece instead

def squares_the_yield_way(n):
    for x in range(n):
        y = x * x
        yield y                           # with this

Instead of this:

do this:

def squares_the_yield_way(n):
    for x in range(n):
        y = x * x
        yield y                           # with this one.

Whenever you find yourself building a list from scratch, yield each piece instead.

added 20 characters in body
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105

Instead ofWhen you find yourself building a list from scratch...

...yield each piece instead

Instead of building a list from scratch...

...yield each piece

When you find yourself building a list from scratch...

...yield each piece instead

deleted 81 characters in body
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
code comments highlight changes
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
deleted 44 characters in body
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link
URL Rewriter Bot
URL Rewriter Bot
Loading
use next function instead of next method, the next method was renamed to __next__ in python-3
Source Link
MSeifert
  • 150.5k
  • 39
  • 342
  • 364
Loading
Use this simple trick to get multi-use out of a generator function.
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
Clarify, "generator" is used in Python 3 docs as a more specific term for the iterator. "Generator function" is therefore unambiguous. Avoiding the term "generator" altogether, which is now ambiguous (some texts use it for the function).
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
the_list is a better name then return_list (more noun-like), and other tweaks
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
oops sequence has specific meaning in Python too, changing to series
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
tie in to double meaning of 'yield'
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
Correct iterator / generator terminology. Calling next(iterator) is Python 2/3 compatible, versus iterator.next() which is Python 2 only, thanks to @Passiday's comment.
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
added 20 characters in body
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
More info. Less snark.
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
Drawing prime attention to the code, which explains it faster.
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
added 93 characters in body
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
added 106 characters in body
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading
Source Link
Bob Stein
  • 16.9k
  • 10
  • 90
  • 105
Loading