The difference between yielding a single value and returning a single value is that yield wraps the value in an iterator, which is also called a stream or enumerator in other languages. A list is one example of an enumerator, and to simplify this answer, you can pretend that all iterators are just lists.
The difference between yielding many values (say, inside a for
loop and returning an iterator (or list), is when the values are calculated. With yield, one value is calculated, and returned to the caller. If the caller doesn't need the whole list of values, the rest of the list is not even calculated.
However, when returning a list, the entire list must be calculated beforehand. Say you have this function:
def findIndex(enumerator, item):
idx = 0
for value in enumerator:
if (value == item):
return idx
idx = idx + 1
It takes an iterator, and searches for an item
, returning the index of that item.
Now, here's where iterators make a difference. Imagine that you are going to call findIndex
like this:
findIndex(gimme_the_values(), 3);
Say that gimme_the_values
is some function which calculates a list of integers; however, let's also say that, the process of calculating those integers takes a long time, for some reason. Maybe, you're scanning through a 1500 page document, looking for every number that occurs in it, and that's the list of values that you're returning.
Now, let's say that the first several numbers to occur in this document are the numbers 7, 1998, 3, and 18; and let's say that the three occurs on the 40th page. If you define gimme_the_values
to use yield, you can stop generating that "list" at page 40 — you'll never even scan for and return the the 18. However, if gimme_the_values
returns a list instead of yielding, you have to scan every page, and generate the whole list, even though you really only need the first 3 in this case.