Two keywords that often confuse beginner Python programmers are yield and return. Both of these keywords have a role to play in Python functions, but they serve different purposes.
The return keyword is used to immediately return one or more values from a function in Python. The yield keyword when used in a function returns an object called “generator object”. You can iterate through a generator object to get values from it one at a time. This way yield provides more efficient memory usage than return especially when working with large data sets.
In this article, we will compare the yield keyword with the return keyword to help you understand their differences and when to use each one.
Let’s start writing some examples of code!
Understanding the Python return Keyword
Do you want to return a value from a function?
Let’s begin by discussing the return statement in Python and see how to use a return statement in a function.
In Python, a return statement is used to exit a function and return a value to the caller. When a function encounters a return statement, it immediately exits and sends the specified value back to the caller. This value can be of any data type, including numbers, strings, lists, or even more complex objects.
With the term “caller” we refer to the line of code in which that specific function has been called.
Here is a simple example to illustrate the use of return with a normal function:
def add_numbers(a, b): result = a + b return result sum = add_numbers(3, 5) print("The sum of the two numbers is:", sum)
This is the output of the final print statement after the execution of the function:
The sum of the two numbers is: 8
In this example, the add_numbers() function takes two arguments, a and b, adds them together, and returns a single value using the return statement on the last line of the function.
In Python, one return statement can return multiple values.
Here is an example of how to return multiple values in a function:
def get_sum_and_product(a, b): sum = a + b product = a * b return sum, product result = get_sum_and_product(3, 5) print(type(result)) print(result)
In this example, the function get_sum_and_product() takes two numbers as inputs and returns their sum and product.
We have added two print statements at the end of the code to print the value returned and its data type (using Python’s type() built-in function).
<class 'tuple'> (8, 15)
You can see that the two values are returned by the function in a tuple. After completing this tutorial, deepen your Python knowledge by going through the Codefather guide about Python tuples.
Introducing the yield Keyword in Python
Now, let’s shift our focus to the yield keyword and learn what is the difference between normal functions using return and functions using yield.
In Python, yield converts a normal function into a generator function. A generator function is a special type of function that allows you to iterate over a sequence of values without creating the entire sequence in memory at once. Every time the yield statement in the function is executed the generator returns a new value. This can be incredibly efficient when working with large data sets.
Let’s learn what happens when you use the yield keyword instead of return in a function.
Here is an example of a simple function using yield:
def count_up_to(n): index = 1 while index <= n: yield index index += 1 counter = count_up_to(5)
As you can see in the code above, there is no return statement in this function, and at every iteration of the while loop the yield statement is executed to “yield” the value of the variable index before increasing it.
So, what is the return value of this function?
Use a print() statement to print the value of the variable counter:
print(counter) [output] <generator object count_up_to at 0x102574110>
Interestingly, this function returns a generator object.
What can you do with a generator object?
A yield statement returns a generator object to the caller. In Python, you can go through the values in a generator object using a for loop.
for num in counter: print(num) [output] 1 2 3 4 5
In this example, the count_up_to() function is a generator function that yields numbers from 1 up to a specified limit n.
When you call count_up_to(5), the generator function doesn’t immediately compute all the numbers from 1 to 5. Instead, it generates and yields each number one at a time when you iterate over it with a for loop.
When Do You Use yield Instead of return in Python?
In Python, yield and return serve different purposes, and neither is inherently better than the other.
- Use return for straightforward calculations and one-time results.
- Choose yield for generating sequences, managing state, and efficient memory usage, especially with large datasets.
The right choice depends on your specific task and requirements.
When you are starting with Python the first step is to have a clear understanding of how to write return statements as these are incredibly important for you to understand Python functions.
Once you have a robust understanding of Python functions then you can look at how to use yield to make your code memory efficient.
What is the Difference Between yield and return in Python?
Now that we have covered the basics of return and yield, let’s delve into the key differences between them:
- return: A function with a return statement terminates when it encounters that statement. It returns a value and exits the function.
- yield: A function with a yield statement becomes a generator function. It yields a value to the caller, and the function’s state is saved. It can be resumed from where it left off, retaining its local variables’ values.
- return: Typically used in regular functions to calculate a value and send it back to the caller.
- yield: Used in generator functions to produce a sequence of values efficiently.
- return: Not meant for creating iterators.
- yield: Designed for creating iterators, allowing lazy evaluation of values.
- return: May consume more memory, especially when dealing with large data sets.
- yield: Minimizes memory usage as it generates values on the fly.
What are the Disadvantages of yield in Python?
While yield is a powerful tool for working with iterators, it’s important to be aware of its limitations and potential drawbacks:
- Complexity: Generator functions can be more complex to write and understand compared to regular functions that use return. They involve managing the function’s state and control flow.
- Single Use: Generator functions are typically designed for single use. Once you have iterated through all the values they yield, you can’t rewind and start over without creating a new instance of the generator.
- Limited Use Cases: yield is most beneficial when dealing with large sequences. For simpler tasks, using return in regular functions is more straightforward.
Can a Function Have Both a yield statement and a return statement?
A function can contain both yield and return statements, but it’s important to understand how they interact. When a function encounters a return statement, it immediately exits, and any subsequent yield statements will not be executed.
Here is an example of code:
def mixed_function(): yield 1 return 2 yield 3 result = mixed_function() print(result)
In this code, we have a function called mixed_function().
The yield statement on the first line of the function returns a generator object. It’s confirmed by the output of the print() statement that shows the value of the result variable:
<generator object mixed_function at 0x1032989e0>
You can iterate through this generator object using a for loop.
for value in result: print(value) [output] 1
Let’s see what happens when you interact with the result variable. It’s not so obvious considering that we have created an unusual function that contains two yield statements and one return statement.
- On the first iteration, the function will execute until it reaches the first yield statement. At this point, the value 1 will be yielded as confirmed by the output of the print() statement in the for loop.
- On the next iteration, the function would typically resume its execution. However, this doesn’t happen due to the return statement immediately after the first yield statement. At this point, the generator is considered exhausted and it raises a StopIteration exception with a value of 2, which is the argument of the return statement.
- The last yield statement, written after the return statement, is never reached because the generator function has already exited with the return statement.
I know, it can be quite complex to understand the first time!
So feel free to go through steps 1, 2, and 3 several times until they are clear to you.
result = mixed_function() print(next(result)) print(next(result)) [output] 1 Traceback (most recent call last): File "/opt/codefather/tutorials/yield_vs_return.py", line 8, in <module> print(next(result)) ^^^^^^^^^^^^ StopIteration: 2
Conclusion: yield vs. return for Functions in Python
Python yield vs. return: after this tutorial which one would you use?
In summary, yield and return in Python are both essential keywords, but they serve different purposes:
- return is used in regular functions to send a value back to the caller and exit the function.
- yield is used in generator functions to create efficient iterators that yield values one at a time, minimizing memory usage.
Choosing between yield and return depends on your specific use case.
If you need to calculate and return a value from a function, return is the way to go. On the other hand, if you want to create an iterator for lazy evaluation or deal with large data sets efficiently, yield is your tool of choice.
Understanding the differences between yield and return will help you write more effective and memory-efficient Python code, designed around your specific needs as a programmer.
Related article: Continue growing your programming knowledge with the detailed Codefather tutorial about Python yield.
Claudio Sabato is an IT expert with over 15 years of professional experience in Python programming, Linux Systems Administration, Bash programming, and IT Systems Design.
With a Master’s degree in Computer Science, he has a strong foundation in Software Engineering and a passion for Robotics with projects that include Raspberry Pi and Arduino platforms.