Image of Python Yield vs Return

ADVERTISEMENT

Introduction

The function is a powerful tool used in many programming languages. In Python, the return statement is used to tell the function to output a specific value to the caller. However, there is another lesser-known statement called the yield can be used to achieve different behavior.

In this article, we discuss the differences between yield and return in Python. In order to do this we'll explore other concepts including iterators and generators.

What is the return statement in Python?

Functions are an essential part of Python that allow blocks of code to be re-used multiple times. Functions can also make use of arguments to make them dynamic so that we can call the same function but change specific values resulting in a different output or flow of instructions.

By using the return statement in a function we can specify the output of the function and end the function call. For example:

>>> def func(x, y):
...     result = x + y
...     return result
... 
>>> 

This example shows a function that takes two variables and returns their sum. The return statement is used to define that the output of the function will be the variable named result, which is the sum of x and y. We can then call the function with different variables:

>>> print(func(1, 2))
3
>>> print(func(3, 4))
7

To learn more about function calls check out the "What is a Function Call?" section in our post Python SyntaxError: Can't Assign To Function Call.

But what happens if we don't include a return statement inside a function? A return statement is actually not required for a valid function definition. In fact, there are many times you won't even need it. For example:

>>> def func(x, y):
...     result = x + y
... 
>>> print(func(1, 2))
None

If we omit the return statement as seen in the previous example, the function returns a default value of None.

As another example, let's assume the only thing we want to achieve is to print the result variable. We could just do that inside the function and then we won't need the return statement:

>>> def func(x, y):
...     result = x + y
...     print(result)
... 
>>> func(1, 2)
3

What is an iterator in Python?

Iteration in the English language means the repetition of a process, which reflects the usage of iterables in Python. An iterable is an object having a structure that can be stepped through one element at a time. For example, strings, lists, and tuples are iterables because you can loop through each element in them one-by-one in order.

An iterator in Python is an object to which you can apply the __next__() method to and iterate through it. We can turn an iterable like a list into an iterator with the iter() built-in function.

>>> a = [1, 2, 3, 4]
>>> iter_a = iter(a)
>>> iter_a
<list_iterator object at 0x7fac2b1d5910>
>>> type(iter_a)
<class 'list_iterator'>
>>> iter_a.__next__()
1
>>> iter_a.__next__()
2
>>> next(iter_a)
3
>>> next(iter_a)
4
>>> next(iter_a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> 

In the example above, we used the iter() function to turn the list into an iterator stored in the variable iter_a. We could also use the __iter__() method to do the same thing. Then we can use the __next__() method or the next() function to iterate through the list. Once we reach the end of the list we get a StopIteration exception. As you might guess, this shows that we can only loop through an iterator once.

We can also run an iterator through a for loop:

>>> iter_a = iter(a)
>>> for num in iter_a:
...     print(num)
... 
1
2
3
4

For loops pair naturally with iterators since they are meant to do just that - call the __next__() method on the iterator to supply the next value to be used in the loop.

What are generators in Python?

In Python, a generator is a specific type of iterator. A generator is an iterator, but an iterator is not a generator. A generator is a type of function that returns an iterator instead of a specific value. This means that the resulting output of the function can be called multiple times via next() to yield successive differing values.

A common form that generators in Python take are "one-line for loops". For example:

>>> b = (n+1 for n in a)
>>> b
<generator object <genexpr> at 0x7fac2b16b580>
>>> next(b)
2
>>> next(b)
3

Here, we create a generator object, with a "one-line for loop" inside parentheses. And since generators are iterators, we can iterate through them with the next function.

As we shall now see, we can also create a generator with a normal function definition by using the yield statement.

What is yield in Python?

The yield statement in Python is specifically used inside function definitions to create generators. For example:

>>> def g():
...     yield 1
...     yield 2
...     yield 3
... 
>>> 
>>> a = g()
>>> type(a)
<class 'generator'>
>>> next(a)
1
>>> next(a)
2
>>> next(a)
3
>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Here, we define a function g with three yield statements. In this example, we learn that we can actually use the yield statement multiple times in a function. The function call is now the type generator. When we iterate through the generator with next(), each value is yielded sequentially.

Another way to use yield is shown below:

>>> def g2(ls):
...     for i in ls:
...             yield i + 1
... 
>>> 
>>> a = [1, 2, 3, 4]
>>> 
>>> b = g2(a)
>>> next(b)
2
>>> next(b)
3
>>> next(b)
4
>>> next(b)
5

Here, we produce the same generator we did in the previous section with the "one-line for loop". Then we iterate through the generator with next.

What's the difference between yield and return?

Both yield and return statements are both used inside function definitions. However, the return statement is only executed once in a single function call, but yield as we have seen in the previous section can be used multiple times in a single function call. Furthermore, the return statement returns a specific variable or expression value, while the yield statement returns a iterator that can be iterated using next().

The yield statement is also more memory efficient than the return statement in certain situations. For example:

>>> ls = [1, 2, 3, 4]
>>> 
>>> def func(ls):
...     new_ls = []
...     for i in ls:
...             new_ls.append(i + 1)
...     return new_ls
... 
>>> 
>>> for i in func(ls):
...     print(i)
... 
2
3
4
5

Here, we want to modify the list ls and then loop through it without changing the original list.

With the return statement, we have to create a new list, modify that list and then return the new list. When looping through the new list, that list will be stored in memory. Now let's see the approach with the yield statement.

>>> ls = [1, 2, 3, 4]
>>>
>>> def func(ls):
...     for i in ls:
...             yield i + 1
... 
>>> for i in func(ls):
...     print(i)
... 
2
3
4
5

We can see that the generator will yield each item in the list with 1 added to it. Now, when we run the for loop on the function, it simply yields the next result from the iterator each time. We no longer have to store an extra list in memory. This makes yield more memory efficient in this case.

Summary

In this article, we compared the yield and return keywords in Python and understood when it is might be correct to use one over the other. We first briefly explored what functions and return statements are in Python. Then we understood what iterables and generators are. We then saw how using yield inside a function makes that function a generator. Finally, we tied all these concepts together to understand the difference between yield and return.

Next Steps

If you're interested in learning more about the basics of Python, coding, and software development, check out our Coding Essentials Guidebook for Developers, where we cover the essential languages, concepts, and tools that you'll need to become a professional developer.

Thanks and happy coding! We hope you enjoyed this article. If you have any questions or comments, feel free to reach out to jacob@initialcommit.io.

Final Notes