Python return Multiple Values

In this article let us learn how to return more than one value from functions in Python.

As programmers, we often come across situations where we need to return multiple values from functions. Python provides us several ways to do this (Yes! More than one way!) and expects “us”, the programmers, to choose one that best fits our use-case.

Let us go ahead and see what those methods are and when to use which one!
For those of you in a hurry here is a cheat-sheet containing all the methods explained in this article.

Cheat-Sheet: Return Multiple Values From Functions in Python

MethodWhen to Use This
1.Separate the values using commasBest method when returning upto 3 values
2.Using Named Tuples* returning a large number of values (more than 3)
* make code more readable while maintaining the performance
3.Pack the values into Dicts* mutable data
* returning a large number of values (more than 3)
4.Pack the values into Lists* ordered data
* indexable data
* mutable data
5.Pack the values into Custom classesreturning closely related values that could benefit from being a class

Don’t worry if this table doesn’t make sense yet, as this table is for those people who just came here to refresh their memories. Each of the above methods is explained in the rest of this article with the help of some examples!

Method#1: Separate the values using commas (The Best Way for returning Up-to 3 values)

Let us start with the best method!
Have a look at the example below.

def calculate_area_n_perimeter(length, breadth):
    area = length * breadth
    perimeter = 2 * (length + breadth)
    return area, perimeter

Area, Perimeter = calculate_area_n_perimeter(10, 5)
print ("Area of rectangle = ", Area)
print ("Perimeter of rectangle = ", Perimeter)

As you can see, the function calculate_area_n_perimeter() simply returns the area and perimeter in Line-4 using the syntax

return area, perimeter

Basically, all we did here is to separate the values being returned using commas! Simple as that!
Of course, this is not limited to just 2 values, you can return any number of values using this syntax!

This is my favorite syntax out of the bunch because it is so simple and intuitive!

When to use this method

If you are returning a small number of values, say less than or equal to 3, then use this method.
This is because the human mind is very good at remembering upto 3 items. Anything more than that and it is easy to make the mistake of having the wrong order at the receiving end.

For example, if Line-6 of Example#1 is changed from

Area, Perimeter = calculate_area_n_perimeter(10, 5)

to

Perimeter, Area = calculate_area_n_perimeter(10, 5)

Then instead of getting the output

Area of rectangle =  50
Perimeter of rectangle =  30

we would get

Area of rectangle =  30
Perimeter of rectangle =  50

which would be a big error!

Always remember the rule of 3!

A Nerdy Side Note: In Python’s view we are still returning a single value!

Python, just like many other programming languages, is built to only return one value!
Then how did we just return multiple values? Let us see how this magic is done!

Have a look at the following interpreter session

>>> a, b = 10, 5
>>> a
10
>>> b
5

This idiom is called “Multiple Assignment”, basically assigning values for more than one value at a time.

Behind the scenes, Python actually uses the “Tuple” datatype to make this magic happen.

Any values separated using commas forms a tuple in Python.

(A Tuple in simple terms is a constant list, which cannot be changed after it is declared)
Have a look below.

>>> c = 20, 10
>>> type(c)
<class 'tuple'>

As you can see, we have used the same exact syntax and when we check the type of the variable c it is actually a tuple!

Similarly, our function calculate_area_n_perimeter(10, 5) returns a single tuple and not multiple values!

>>> type(calculate_area_n_perimeter(10, 5))
>>> <class 'tuple'>

Probably when you were learning Python, you would have used tuples like shown below

>>> d = (1,2,3)
>>> type(d)
<class 'tuple'>

But these braces are completely optional! Any value separated by commas are tuples in Python. In fact even this is a tuple!

>>> e = 1,
>>> type(e)
<class 'tuple'>

One case you would certainly need braces is when you are making a tuple of tuples like shown below!

>>> f = (1, (10, 20), (30, 40, 50))
>>> type(f)
<class 'tuple'>

Unless we do “multiple assignment” or “return multiple values”, it is considered best practice to use braces whenever you use tuples to explicitly tell the reader that you are using tuples as this improves readability!

Another use of tuples is

  • If your return values are ordered by nature (like x, y coordinates) then use tuples.

In this case, even if you are returning more than 3 values, you can still use Tuples as unpacking ordered values is less error-prone!

At times you may come across a situation where you might want to return more than 3 values that are not ordered. Let us see what we can do in those situations in the next section!

Method#2: Using Named Tuples (The Best Way for returning more than 3 values)

As we saw above in Method#1, tuples are a great way to return multiple values from a function, but things can get out of control really fast if we are sending more than 3 values.

This is because unpacking it on the receiving side will be very error-prone and can lead to bugs in the code, which in turn can result in a lot of hours wasted on debugging.

As professionals, we must always be aware of the tools given to us by the programming language (Python in this case) and make sure to pick the right tool for the right job.

The “tool” that can solve our problems here is the class called “Named Tuples”.

According to the official python website

Named tuples assign meaning to each position in a tuple and allow for more readable, self-documenting code. They can be used wherever regular tuples are used, and they add the ability to access fields by name instead of position index.

python.org

Let us first experiment a little bit with named tuples. Have a look at the interpreter session below.

>>> from collections import namedtuple
>>> Rectangle = namedtuple('Rectangle', ['length', 'breadth'])
>>> rect = Rectangle(10, 5)
>>> rect[0]
10
>>> rect.length
10
>>> rect[1]
5
>>> rect.breadth
5

As you can see we can access the items inside the namedtuple by

  • using the index like regular tuples, and
  • using the dot notation like a class!

On top of giving us this functionality, named tuples are also lightweight and do not require more memory compared to the regular “non-named” version of the tuples.

Now that we have learned a little bit about Named-Tuples, let us see an example of how we can use them in our programs!

from collections import namedtuple
Results = namedtuple('Results', ['area', 'perimeter'])

def calculate_area_n_perimeter(length, breadth):
    area = length * breadth
    perimeter = 2 * (length + breadth)
    return_vals = Results(area, perimeter)
    return return_vals

return_values = calculate_area_n_perimeter(10, 5)
print ("Area of rectangle = ", return_values.area)
print ("Perimeter of rectangle = ", return_values.perimeter)

As you can see above, we have edited Example#1 to use namedtuple instead. Here

  • In Line-1 we have imported the namedtuple class
  • In Line-2 we have made the lightweight “Results” class with just one line of code, to hold 2 members “area” and “perimeter
  • In Line-7 we have made an object of “Results” class and Line-8 returns this object
  • In Line-10 we have received back the return values, but this time in the form of a namedtuple object and
  • In Lines-11 & 12 we print them out using the dot operator!

Simple as that!

When to use this method?

This method is best when

  • you wish to improve the readability of your code while returning multiple values at the same time
  • you want the values to be immutable at the receiving side (since tuples are immutable by nature)
  • you are working on a project that runs on constrained hardware that requires efficiency and performance

Cons of this method

namedtuple might not be your best choice if

  • you have to make changes to the returned values or
  • you need to add more items to the returned container.

You cannot do those with tuples as they are essentially constant lists!

But fret not, as when situations like that do come up we have methods 3 and 4 to help us!

Method#3: Pack the values into Dicts (Best way for sending values that needs changes)

Take a look at the below program.

def calculate_area_n_perimeter(length, breadth):
    ret_dict = {}
    area = length * breadth
    perimeter = 2 * (length + breadth)
    ret_dict['area'] = area
    ret_dict['perimeter'] = perimeter
    return ret_dict

results = calculate_area_n_perimeter(10, 5)
print ("Area of rectangle = " results['area'])
print ("Perimeter of rectangle = " results['perimeter'])

When we use dicts we can

  • change the values on the receiving side
  • add more values to the container
>>> results['area'] = 10
>>> results['color'] = 'red'

I leave it to you to try out what happens when you do the same above with tuples and namedtuples!

Another advantage of using dictionaries is that you can add fields to the returned dictionary without breaking existing code! (I am sure that the readers who are experienced programmers will appreciate this cool property!)

Method#4: Pack the values into Lists (Best way for sending mutable data that does not need names)

Have a look at the example below to see how lists can be used to return multiple values

def get_fav_activities():
    activity_list = []
    activity = input("please write your most favorite activity: ")
    activity_list.append(activity)
    activity = input("please write your 2nd most favorite activity: ")
    activity_list.append(activity)
    activity = input("please write your 3rd most favorite activity: ")
    activity_list.append(activity)
    return activity_list

results = get_fav_activities()
print ("You like doing",  results[0], results[1], "and", results[2], "in that order!")

Running this code will give an output like this

please write your most favorite activity: coding
please write your 2nd most favorite activity: eating
please write your 3rd most favorite activity: sleeping
You like doing coding eating and sleeping in that order!

When to use this method?

This method of using lists is useful when you have some data

  • which the values are ordered and
  • at the receiving side, all you need is the index to access the return values.
  • and you wish to append stuff to the list if needed.

The above example is just one crude example of such a situation.

But remember, a tuple is always preferable to a list when mutability is not a requirement!

Method#5: Pack the values into Custom classes (Best way for sending closely related data)

The next method is to make a custom class, pack the data into an object and send out the object!

Have a look at the example below.

class Results:
  def __init__(self, area, perimeter):
    self.area = area
    self.perimeter = perimeter

def calculate_area_n_perimeter(length, breadth):
    area = length * breadth
    perimeter = 2 * (length + breadth)
    return Results(area, perimeter)

results = calculate_area_n_perimeter(10, 5)
print ("Area of rectangle = ", results.area)
print ("Perimeter of rectangle = ", results.perimeter)

If your class does not need any methods you can also make use of data classes provided by Python. This way you can be explicit about the fact that this class doesn’t have any methods.

The example below shows how this can be done.

from dataclasses import dataclass

@dataclass
class Results:
    area: int
    perimeter: int

def calculate_area_n_perimeter(length, breadth):
    area = length * breadth
    perimeter = 2 * (length + breadth)
    return Results(area, perimeter)

results = calculate_area_n_perimeter(10, 5)
print ("Area of rectangle = ", results.area)
print ("Perimeter of rectangle = ", results.perimeter)

When to use this method?

You can use the above methods when it makes sense to group the data together into a single class.

The decision of whether to use an ordinary class or a data class comes down to your use case. If you don’t see a use for member functions, I suggest you go with the dataclass instead of the regular one.

Table of all methods

Here is the cheat sheet again from the beginning of the article again. I hope this time around you will be able to make better sense of it.

No.MethodExample usageWhen to Use This
1Separate the values using commasdef calculate_area_n_perimeter(length, breadth):
area = length * breadth
perimeter = 2 * (length + breadth)
return area, perimeter
Best method when returning upto 3 values
2Using Named Tuplesfrom collections import namedtuple

Results = namedtuple(‘Results’, [‘area’, ‘perimeter’])

def calculate_area_n_perimeter(length, breadth):
area = length * breadth
perimeter = 2 * (length + breadth)
return_vals = Results(area, perimeter)
return return_vals
* returning a large number of values (more than 3)
* make code more readable while maintaining the performance
3Pack the values into Dictsdef calculate_area_n_perimeter(length, breadth):
ret_dict = {}
area = length * breadth
perimeter = 2 * (length + breadth)
ret_dict[‘area’] = area
ret_dict[‘perimeter’] = perimeter
return ret_dict
* mutable data
* returning a large number of values (more than 3)
4Pack the values into Listsdef get_fav_activities():
activity_list = []
activity = input(“please write your most favorite activity: “)
activity_list.append(activity)
activity = input(“please write your 2nd most favorite activity: “)
activity_list.append(activity)
activity = input(“please write your 3rd most favorite activity: “)
activity_list.append(activity)
return activity_list
* ordered data
* indexable data
* mutable data
5Pack the values into Custom classesclass Results:
def init(self, area, perimeter):
self.area = area
self.perimeter = perimeter

def calculate_area_n_perimeter(length, breadth):
area = length * breadth
perimeter = 2 * (length + breadth)
return Results(area, perimeter)
returning closely related values that could benefit from being a class

And with that, I will end this article. I hope you enjoyed reading it!

Feel free to share it with your friends and colleagues.

Here are some more articles that you might enjoy.

Related Articles

Python’s [:] Notation Explained with Examples!

Exceptions in Python: Everything You Need To Know!

References

The content of this article is inspired by the following sources.

python.org
python.org
StackOverflow Question
Quora Question

Photo of author
Editor
Balaji Gunasekaran
Balaji Gunasekaran is a Senior Software Engineer with a Master of Science degree in Mechatronics and a bachelor’s degree in Electrical and Electronics Engineering. He loves to write about tech and has written more than 300 articles. He has also published the book “Cracking the Embedded Software Engineering Interview”. You can follow him on LinkedIn