🔄 Returning Values
Return statements are how functions communicate results back to the code that calls them. Python functions can return single values, multiple values, or different values based on conditions, making them powerful tools for data processing and decision-making workflows.
# Different types of return values
def calculate_stats(numbers):
"""Return multiple statistics about a list of numbers"""
if not numbers:
return None, None, None # Handle empty list
total = sum(numbers)
average = total / len(numbers)
maximum = max(numbers)
return total, average, maximum # Return multiple values
# Use the returned values
scores = [85, 92, 78, 96, 88]
total, avg, max_score = calculate_stats(scores)
print(f"Total: {total}, Average: {avg:.1f}, Max: {max_score}")
🎯 Single Value Returns
Returning single values is the most common pattern, where functions perform calculations or operations and send back one result to the caller.
def calculate_discount(price, discount_percent):
"""Calculate discounted price"""
discount_amount = price * (discount_percent / 100)
return price - discount_amount
def validate_password(password):
"""Check if password meets requirements"""
if len(password) < 8:
return False
if not any(char.isdigit() for char in password):
return False
return True
# Single value returns
discounted_price = calculate_discount(100, 15)
is_valid = validate_password("mypass123")
print(f"Discounted price: ${discounted_price}")
print(f"Password valid: {is_valid}")
⚡ Multiple Value Returns
Python functions can return multiple values simultaneously using tuple unpacking, enabling complex calculations that produce several related results in one operation.
def parse_name(full_name):
"""Split full name into first and last name"""
parts = full_name.strip().split()
if len(parts) >= 2:
return parts[0], parts[-1] # First and last
return parts[0], "" # Only first name provided
def get_file_info(filename):
"""Extract filename and extension"""
if '.' in filename:
name, extension = filename.rsplit('.', 1)
return name, extension
return filename, ""
# Unpack multiple return values
first, last = parse_name("Alice Johnson")
name, ext = get_file_info("document.pdf")
print(f"Name: {first} {last}")
print(f"File: {name}, Extension: {ext}")
🚀 Conditional Returns
Functions often need to return different values based on input conditions or calculation results, providing flexible responses to various scenarios.
def get_grade_info(score):
"""Return letter grade and pass/fail status"""
if score >= 90:
return "A", True, "Excellent"
elif score >= 80:
return "B", True, "Good"
elif score >= 70:
return "C", True, "Satisfactory"
elif score >= 60:
return "D", True, "Passing"
else:
return "F", False, "Needs Improvement"
def process_user_login(username, password):
"""Return login result with appropriate message"""
if not username:
return False, "Username required"
if not password:
return False, "Password required"
if len(password) < 6:
return False, "Password too short"
return True, "Login successful"
# Handle different return scenarios
grade, passed, comment = get_grade_info(87)
success, message = process_user_login("alice", "secret123")
print(f"Grade: {grade}, Passed: {passed}, {comment}")
print(f"Login: {success}, {message}")
📊 Return Value Types Comparison
Return Type | Syntax | Use Case | Example |
---|---|---|---|
Single Value | return value | Simple calculations | return price * 1.08 |
Multiple Values | return val1, val2 | Related calculations | return width, height |
Conditional | if condition: return val1; else: return val2 | Different scenarios | Grade calculation |
Early Return | if error: return None | Error handling | Input validation |
None (implicit) | No return statement | Side effects only | Print or file operations |
🌟 Early Returns for Error Handling
Early returns improve code readability by handling error conditions first, allowing the main logic to proceed without nested if statements.
def calculate_bmi(weight, height):
"""Calculate BMI with input validation"""
# Early returns for invalid input
if weight <= 0:
return None, "Weight must be positive"
if height <= 0:
return None, "Height must be positive"
# Main calculation logic
bmi = weight / (height ** 2)
# Categorize BMI
if bmi < 18.5:
category = "Underweight"
elif bmi < 25:
category = "Normal"
elif bmi < 30:
category = "Overweight"
else:
category = "Obese"
return bmi, category
# Test with different inputs
bmi1, result1 = calculate_bmi(70, 1.75)
bmi2, result2 = calculate_bmi(-5, 1.75)
print(f"BMI 1: {bmi1:.1f} ({result1})")
print(f"BMI 2: {bmi2} - {result2}")
💡 Returning Data Structures
Functions can return complex data structures like lists, dictionaries, or custom objects to organize related information effectively.
def create_user_summary(name, age, email):
"""Create a user summary dictionary"""
return {
'name': name,
'age': age,
'email': email,
'id': name.lower().replace(' ', '_'),
'active': True
}
def get_even_odd_numbers(numbers):
"""Separate numbers into even and odd lists"""
even = [n for n in numbers if n % 2 == 0]
odd = [n for n in numbers if n % 2 == 1]
return even, odd
def generate_report_data(sales_data):
"""Generate comprehensive sales report"""
return {
'total_sales': sum(sales_data),
'average_sale': sum(sales_data) / len(sales_data),
'best_day': max(sales_data),
'total_days': len(sales_data),
'sales_list': sales_data
}
# Work with returned data structures
user = create_user_summary("Alice Johnson", 28, "alice@example.com")
even_nums, odd_nums = get_even_odd_numbers([1, 2, 3, 4, 5, 6])
report = generate_report_data([100, 150, 200, 175])
print(f"User ID: {user['id']}")
print(f"Even: {even_nums}, Odd: {odd_nums}")
print(f"Sales report: {report['total_sales']} total")
📚 Practical Applications
API Response Functions
Functions that return structured data work perfectly for API responses where different endpoints need to return consistent formats.
def api_success(data, message="Success"):
"""Return standardized API success response"""
return {
'success': True,
'message': message,
'data': data,
'timestamp': '2024-01-15 10:30:00'
}
def api_error(error_message, error_code=400):
"""Return standardized API error response"""
return {
'success': False,
'error': error_message,
'code': error_code,
'timestamp': '2024-01-15 10:30:00'
}
# Use standardized responses
user_data = {'name': 'Alice', 'id': 123}
success_response = api_success(user_data, "User retrieved successfully")
error_response = api_error("User not found", 404)
print("Success:", success_response)
print("Error:", error_response)
Data Validation Functions
Functions that return validation results help create robust applications with clear error handling.
def validate_form_data(form_data):
"""Validate form data and return results"""
errors = []
if not form_data.get('name'):
errors.append("Name is required")
if not form_data.get('email') or '@' not in form_data['email']:
errors.append("Valid email is required")
if form_data.get('age', 0) < 18:
errors.append("Must be 18 or older")
if errors:
return False, errors
return True, "Form data is valid"
# Test validation
valid_form = {'name': 'Alice', 'email': 'alice@example.com', 'age': 25}
invalid_form = {'name': '', 'email': 'invalid', 'age': 16}
is_valid1, result1 = validate_form_data(valid_form)
is_valid2, result2 = validate_form_data(invalid_form)
print(f"Valid form: {is_valid1} - {result1}")
print(f"Invalid form: {is_valid2} - {result2}")
Hands-on Exercise
Create a function that calculates both the area and perimeter of a rectangle. Return both values so they can be used separately.
def rectangle_calculations(length, width):
# TODO: Calculate area (length * width)
# TODO: Calculate perimeter (2 * (length + width))
# TODO: Return both area and perimeter
pass
# TODO: Test the function and unpack the results
area, perimeter = rectangle_calculations(5, 3)
print(f"Area: {area}")
print(f"Perimeter: {perimeter}")
Solution and Explanation 💡
Click to see the complete solution
def rectangle_calculations(length, width):
# Calculate area (length * width)
area = length * width
# Calculate perimeter (2 * (length + width))
perimeter = 2 * (length + width)
# Return both area and perimeter
return area, perimeter
# Test the function and unpack the results
area, perimeter = rectangle_calculations(5, 3)
print(f"Area: {area}")
print(f"Perimeter: {perimeter}")
Key Learning Points:
- 📌 Multiple return values: Use commas to return multiple values
return value1, value2
- 📌 Tuple unpacking: Assign multiple return values to separate variables
- 📌 Related calculations: Perfect for functions that compute related values
- 📌 Function organization: One function can perform multiple related calculations
Learn more about variable scope to understand how variables behave inside and outside functions.
Test Your Knowledge
Test what you've learned about returning values:
What's Next?
Now that you understand how functions return data, you're ready to learn about variable scope. Understanding where variables can be accessed is crucial for writing functions that work correctly with data.
Ready to continue? Check out our lesson on Variable Scope.
Was this helpful?
Track Your Learning Progress
Sign in to bookmark tutorials and keep track of your learning journey.
Your progress is saved automatically as you read.