Table of Contents
Introduction
Why Return Multiple Values?
Real-World Scenario: Real-Time Health Monitoring in Wearable Devices
Methods to Return Multiple Values
Complete Implementation with Test Cases
Best Practices for Clean and Maintainable Code
Conclusion
1. Introduction
In many programming languages, functions are limited to returning a single value. But Python empowers developers with elegant, built-in ways to return multiple values—making code more expressive, efficient, and aligned with real-world logic.
This article explores practical techniques to return multiple results from a function, grounded in a compelling use case from wearable health tech, and delivers production-ready, thoroughly tested code.
2. Why Return Multiple Values?
Real-world operations rarely produce just one output. Consider:
A sensor reading that returns heart rate, oxygen level, and confidence score
A financial calculation that yields profit, tax, and net amount
A machine learning model that outputs predictions, probabilities, and processing time
Returning multiple values avoids:
Python makes this natural—no boilerplate required.
3. Real-World Scenario: Real-Time Health Monitoring in Wearable Devices
Modern smartwatches continuously monitor users’ vital signs. Every 10 seconds, a function processes raw sensor data and must return:
This trio is used by:
The UI to display live stats
An alert system to trigger medical warnings
A cloud sync service to log trends
![PlantUML Diagram]()
Returning all three in one call ensures atomicity, consistency, and performance, critical in life-critical systems.
4. Methods to Return Multiple Values
1. Return a Tuple
def read_vitals():
return 72, 98, 95 # heart_rate, spo2, quality
2. Return a Dictionary
def read_vitals():
return {
"heart_rate": 72,
"spo2": 98,
"quality": 95
}
3. Return a Named Tuple (Best of Both Worlds)
from collections import namedtuple
Vitals = namedtuple('Vitals', ['heart_rate', 'spo2', 'quality'])
def read_vitals():
return Vitals(72, 98, 95)
4. Return a Dataclass (For Complex or Evolving Data)
from dataclasses import dataclass
@dataclass
class Vitals:
heart_rate: int
spo2: int
quality: int
def read_vitals():
return Vitals(72, 98, 95)
Rule of thumb: Use tuples for simple, fixed-size returns; named tuples or dataclasses for clarity and scalability.
5. Complete Implementation with Test Cases
![PlantUML Diagram]()
from collections import namedtuple
import unittest
# Define a clean return type
Vitals = namedtuple('Vitals', ['heart_rate', 'spo2', 'quality'])
def process_sensor_data(raw_signal: list) -> Vitals:
"""
Simulates processing raw PPG sensor data from a wearable.
Returns heart rate (BPM), SpO2 (%), and signal quality (0-100).
"""
if not raw_signal:
return Vitals(0, 0, 0)
# Simplified logic: in reality, this involves FFT, filtering, etc.
avg = sum(raw_signal) / len(raw_signal)
heart_rate = min(180, max(40, int(avg * 0.8 + 60)))
spo2 = min(100, max(80, int(avg * 0.5 + 85)))
quality = min(100, max(0, int(avg * 2)))
return Vitals(heart_rate, spo2, quality)
class TestMultiValueReturn(unittest.TestCase):
def test_normal_reading(self):
raw = [100, 105, 98, 102, 101]
vitals = process_sensor_data(raw)
self.assertIsInstance(vitals, Vitals)
self.assertGreater(vitals.heart_rate, 40)
self.assertLessEqual(vitals.spo2, 100) # Fixed: allow 100
self.assertGreaterEqual(vitals.quality, 0)
def test_empty_input(self):
vitals = process_sensor_data([])
self.assertEqual(vitals, Vitals(0, 0, 0))
def test_unpacking(self):
hr, spo2, qual = process_sensor_data([90])
expected_hr = min(180, max(40, int(90*0.8 + 60))) # 132
expected_spo2 = min(100, max(80, int(90*0.5 + 85))) # 100 (capped)
expected_qual = min(100, max(0, int(90*2))) # 100 (capped)
self.assertEqual(hr, expected_hr)
self.assertEqual(spo2, expected_spo2)
self.assertEqual(qual, expected_qual)
if __name__ == "__main__":
# Simulate real-time reading
raw_data = [95, 97, 96, 94, 98]
hr, spo2, quality = process_sensor_data(raw_data)
print(f" Heart Rate: {hr} BPM")
print(f" SpOâ‚‚: {spo2}%")
print(f" Signal Quality: {quality}/100")
if quality < 70:
print(" Warning: Poor signal quality!")
if spo2 < 90:
print(" Critical: Low oxygen saturation!")
# Run tests
unittest.main(argv=[''], exit=False, verbosity=2)
![1]()
6. Best Practices for Clean and Maintainable Code
Prefer named tuples or dataclasses over plain tuples when readability matters.
Never return inconsistent types (e.g., sometimes tuple, sometimes dict).
Document return types using type hints (-> Vitals
).
Use unpacking for clean caller code: a, b, c = func()
Avoid returning too many values (>4)—consider a class or split into multiple functions.
In performance-critical paths, plain tuples are fastest; for APIs, use structured types.
7. Conclusion
Returning multiple values isn’t just a Python convenience—it’s a design enabler for systems that mirror real-world complexity. In health tech, getting heart rate, oxygen, and quality in one atomic call ensures reliability and responsiveness. By choosing the right return strategy—tuple, named tuple, or dataclass—you balance simplicity, clarity, and scalability. Remember: good functions don’t just compute—they communicate. And in Python, they can say more than one thing at once.