Skip to content

Function Return in Python: A Comprehensive Guide

[

The Python return Statement: Usage and Best Practices

The Python return statement is a key component of functions and methods. It allows you to send Python objects back to the caller code, known as the function’s return value. Understanding how to use the return statement effectively is crucial in writing Pythonic and robust functions.

In this tutorial, you will learn:

1. How to use the Python return statement in your functions:

  • Explicit return Statements
  • Implicit return Statements

2. Returning vs Printing

3. Returning Multiple Values

4. Best Practices for Using the Python return Statement:

  • Returning None Explicitly
  • Remembering the Return Value
  • Avoiding Complex Expressions
  • Returning Values vs Modifying Globals
  • Using return With Conditionals
  • Returning True or False
  • Short-Circuiting Loops
  • Recognizing Dead Code
  • Returning Multiple Named-Objects

5. Returning Functions: Closures

6. Taking and Returning Functions: Decorators

7. Returning User-Defined Objects: The Factory Pattern

8. Using return in try … finally Blocks

9. Using return in Generator Functions

10. Conclusion

To help you understand these concepts better, this tutorial provides detailed explanations and includes step-by-step sample code that you can run and experiment with.

Getting Started With Python Functions

Before diving into the specifics of the return statement, it’s important to familiarize yourself with how functions work in Python. Functions allow you to assign a name to a code block that performs a specific computation and can be reused throughout your code. These named code blocks are commonly referred to as subroutines, routines, procedures, or functions.

To call a function, you simply use its name followed by parentheses. For example:

def say_hello():
print("Hello, world!")
say_hello()

Output:

Hello, world!

In the example above, we defined a function called say_hello() that prints “Hello, world!“. When we call the function using say_hello(), the code inside the function is executed, resulting in the output “Hello, world!“.

Understanding the Python return Statement

Now let’s dive into the specifics of the Python return statement. The return statement allows you to specify the value or values that should be sent back to the caller code.

Explicit return Statements

To explicitly return a value from a function, you use the return keyword followed by the value you want to return. Here’s an example:

def add_numbers(a, b):
return a + b
result = add_numbers(5, 3)
print(result)

Output:

8

In the example above, the add_numbers() function takes two arguments, a and b, and returns the sum of the two numbers. The returned value is then stored in the result variable and printed to the console.

Implicit return Statements

If a function doesn’t have an explicit return statement, it will implicitly return None, which serves as a placeholder for the absence of a value. Here’s an example:

def say_hello():
print("Hello, world!")
result = say_hello()
print(result)

Output:

Hello, world!
None

In this example, the say_hello() function doesn’t have a return statement. As a result, it implicitly returns None. When we assign the result of calling say_hello() to the variable result and print it, we see that None is returned.

Returning vs Printing

It’s important to understand the difference between returning a value from a function and printing a value within a function.

Returning a value allows you to use the result of a function in further computations or assign it to a variable, while printing a value within a function simply displays it on the console but doesn’t make it available for further use.

For example:

def square(number):
return number ** 2
result = square(3)
print(result)

Output:

9

In this example, the square() function returns the square of the number argument. The returned value is then stored in the result variable and printed to the console.

If we were to print the square value directly within the function instead of returning it, we wouldn’t be able to use it outside the function:

def square(number):
print(number ** 2)
square(3)

Output:

9

In this modified example, the square() function prints the square of the number argument directly. When we call square(3), the square value of 9 is printed to the console. However, since there is no return statement, we cannot capture the square value for further computations or assign it to a variable.

So, the choice between returning a value or printing a value within a function depends on whether you need to use the result in subsequent code or simply display it on the console.

Returning Multiple Values

Python allows you to return multiple values from a function by separating them with commas. This feature is often used to conveniently pack and unpack related values. Here’s an example:

def get_name_and_age():
name = "Alice"
age = 30
return name, age
person = get_name_and_age()
print(person)
print(person[0])
print(person[1])

Output:

('Alice', 30)
Alice
30

In this example, the get_name_and_age() function returns the name and age as a tuple. When we call get_name_and_age() and assign the result to the person variable, we get a tuple with both values. We can access each value using indexing, as demonstrated by printing person[0] and person[1].

You can also directly assign the returned values to separate variables using tuple unpacking:

name, age = get_name_and_age()
print(name)
print(age)

Output:

Alice
30

In this modified example, the returned values are assigned to the name and age variables directly. This allows us to access and use each value individually.

Returning multiple values is a powerful feature that allows you to group related data together and easily work with it in your code.

Using the Python return Statement: Best Practices

When using the return statement in your functions, it’s important to follow best practices to ensure your code is clear, maintainable, and efficient. Here are some best practices to keep in mind:

Returning None Explicitly

If a function doesn’t have a meaningful value to return, it’s good practice to explicitly return None instead of relying on implicit return statements. This makes the code more self-explanatory and avoids any potential confusion. Here’s an example:

def log_message(message):
if len(message) > 0:
print(message)
else:
return None
result = log_message("Hello, world!")
print(result)

Output:

Hello, world!
None

In this example, the log_message() function prints the message if it has a length greater than 0. Otherwise, it explicitly returns None to indicate that no meaningful value is being returned. When we print the result of calling log_message("Hello, world!"), we see the message being printed and None being returned.

Remembering the Return Value

When calling a function that returns a value, it’s good practice to assign the returned value to a variable for future use or further computations. This makes your code more readable and allows you to easily refer back to the returned value without re-executing the function. Here’s an example:

def calculate_average(numbers):
total = sum(numbers)
average = total / len(numbers)
return average
grades = [85, 90, 92, 88]
average_grade = calculate_average(grades)
print(average_grade)

Output:

88.75

In this example, the calculate_average() function takes a list of numbers and calculates the average grade. The returned average value is then assigned to the average_grade variable, making it easier to refer back to the result.

Avoiding Complex Expressions

When using the return statement, it’s generally considered best practice to avoid including complex expressions or calculations within the return statement itself. Instead, break down the calculation into smaller steps to improve code readability and maintainability. Here’s an example:

def calculate_discounted_price(original_price, discount):
discounted_price = original_price - (original_price * discount)
return discounted_price
product_price = 100
discount_rate = 0.2
final_price = calculate_discounted_price(product_price, discount_rate)
print(final_price)

Output:

80.0

In this example, the calculate_discounted_price() function calculates the discounted price of a product based on the original price and a discount rate. By breaking down the calculation into separate steps within the function, the return statement is kept simple and easier to understand.

Returning Values vs Modifying Globals

In general, it’s recommended to design your functions to return values instead of directly modifying global variables. This helps to encapsulate functionality and makes your code more modular and reusable.

Returning values allows you to control how the function’s result is used without affecting other parts of your code. It also makes it easier to test and debug your functions since their behavior is isolated and predictable.

name = "Alice"
def greet():
global name # Don't do this!
name = "Bob"
print("Hello, " + name)
greet()
print(name)

Output:

Hello, Bob
Bob

In this example, the greet() function modifies the global name variable to “Bob” instead of returning a value. While this code works, it’s generally considered better practice to have the function return a value and have the caller code decide how to use that value:

def get_greeting():
return "Hello, Bob"
greeting = get_greeting()
print(greeting)

Output:

Hello, Bob

In this modified example, the get_greeting() function returns the greeting as a string. The caller code then decides how to use that returned value, which leads to more flexible and modular code.

Using return With Conditionals

Often, you may need to use conditional statements within your functions to handle different cases or scenarios. In these situations, it’s good practice to have a single return statement at the end of the function to ensure a consistent and predictable flow of execution. Here’s an example:

def get_grade(score):
if score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 70:
return "C"
elif score >= 60:
return "D"
else:
return "F"
student_score = 85
student_grade = get_grade(student_score)
print(student_grade)

Output:

"B"

In this example, the get_grade() function takes a score parameter and returns the corresponding grade based on a series of conditional statements. By having a single return statement at the end of the function, we ensure that only one value is returned and that the flow of execution is clear.

Returning True or False

Sometimes, you may want to write functions that return a Boolean value (True or False) based on certain conditions. In these cases, it’s good practice to have the function return the appropriate Boolean value directly, without using conditional statements. Here’s an example:

def is_even(number):
return number % 2 == 0
print(is_even(4))
print(is_even(7))

Output:

True
False

In this example, the is_even() function takes a number as input and directly returns True or False based on whether the number is even or not. By returning the Boolean value directly, we avoid unnecessary use of conditional statements and make the function’s behavior more explicit.

Short-Circuiting Loops

When using loops in your functions, it’s good practice to use the return statement to exit the loop prematurely if a certain condition is met. This is known as short-circuiting the loop and can help improve performance and reduce unnecessary computations. Here’s an example:

def find_number(numbers, target):
for number in numbers:
if number == target:
return True
return False
list_of_numbers = [1, 2, 3, 4, 5]
target_number = 3
found = find_number(list_of_numbers, target_number)
print(found)

Output:

True

In this example, the find_number() function takes a list of numbers and a target number. It loops through the list and returns True as soon as it finds a number that matches the target. If no match is found, it returns False. By short-circuiting the loop, we avoid unnecessary iterations and end the function as soon as the target is found.

Recognizing Dead Code

When using the return statement, it’s important to be aware of any dead code that appears after the return statement. Dead code refers to any code that is written but never executed due to an earlier return statement. Keeping your code clean and free of dead code helps improve readability and maintainability. Here’s an example:

def is_positive(number):
if number > 0:
return True
else:
return False
print("This code is never reached")
positive = is_positive(5)
print(positive)

Output:

True

In this example, the is_positive() function returns True if the number is greater than 0 and False otherwise. The print() statement that follows the return statement is considered dead code because it is never executed. Removing this dead code improves the clarity and efficiency of the function.

Returning Multiple Named-Objects

In addition to returning multiple values as tuples, you can also return multiple named objects using techniques such as dictionaries or classes. This allows you to provide more descriptive names for the returned values and improves code readability. Here’s an example using a dictionary:

def get_person_info():
return {
"name": "Alice",
"age": 30,
"city": "New York"
}
person_info = get_person_info()
print(person_info["name"])
print(person_info["age"])
print(person_info["city"])

Output:

Alice
30
New York

In this example, the get_person_info() function returns a dictionary with information about a person. By returning a dictionary, we can access each piece of information using descriptive keys, making the code more readable and organized.

Conclusion

The Python return statement is a powerful tool for sending values back to the caller code from functions. By understanding how to use the return statement effectively, you can write more readable, maintainable, and efficient code.

In this tutorial, you learned about the different aspects of the return statement, including explicit and implicit return statements, returning vs printing, returning multiple values, and best practices for using the return statement. Armed with this knowledge, you can enhance your Python programming skills and create better functions that make your code more streamlined and effective.