Return Values, Unpacking, and Multi-Result Design
The phrase "Python can return multiple values" is very common, but a more accurate way to put it is: Python packs multiple return values into a tuple, which you then unpack on the calling side.
The Most Basic Return
def square(x):
return x * x
Returning Multiple Values
def min_max(values):
return min(values), max(values)
low, high = min_max([3, 1, 5, 2])
This is essentially equivalent to:
def min_max(values):
return (min(values), max(values))
Unpacking
point = (3, 5)
x, y = point
Star unpacking is also very common:
first, *middle, last = [1, 2, 3, 4, 5]
When to return a tuple
Suitable for these situations:
- Small number of return values
- The order of return values is clear
- The values naturally belong together
Examples: coordinates, min and max, width and height.
When to return a dictionary or data class
If the number of return values grows, the order becomes hard to remember, or the meaning isn't obvious enough, don't force a tuple.
def get_user():
return {
"name": "alice",
"score": 95,
"city": "Chengdu",
}
Going further, you can use dataclass:
from dataclasses import dataclass
@dataclass
class User:
name: str
score: int
city: str
return and yield are not the same
If a function gives results all at once, use return.
If a function wants to produce results one at a time, use a generator with yield:
def countdown(n):
while n > 0:
yield n
n -= 1
My own decision criteria
- Two or three results with clear meaning: tuple
- Many fields with meaning that needs to be explicit: dictionary or data class
- Want to produce results incrementally: generator