Functions β
Learn to create reusable code blocks that make your programs modular, organized, and easier to maintain
π Function Definition β
Functions are like recipes - they take ingredients (parameters), follow steps (code), and produce a result (return value).
Think of it like this: Instead of writing the same cooking instructions every time, you create a recipe once and use it whenever needed.
Basic Function β
def greet():
"""A simple function that prints a greeting."""
print("Hello, World!")
print("Welcome to Python programming!")
# Call the function
greet()
# Expected output:
# Hello, World!
# Welcome to Python programming!Function with Parameters β
def greet(name):
"""Greet a person by name."""
print(f"Hello, {name}!")
print(f"Nice to meet you, {name}!")
# Call with different arguments
greet("Alice")
greet("Bob")
# Expected output:
# Hello, Alice!
# Nice to meet you, Alice!
# Hello, Bob!
# Nice to meet you, Bob!π Return Values β
Functions can give back results using the return statement - like a vending machine that takes your money and gives you a snack.
Function with Return Value β
def add(x, y):
"""Add two numbers and return the result."""
result = x + y
print(f"Adding {x} + {y}")
return result
def multiply(x, y):
"""Multiply two numbers and return the result."""
return x * y
# Use return values
sum_result = add(5, 3)
print(f"Sum: {sum_result}")
product = multiply(4, 6)
print(f"Product: {product}")
# Chain function calls
final_result = add(multiply(2, 3), 4)
print(f"Final result: {final_result}")
# Expected output:
# Adding 5 + 3
# Sum: 8
# Product: 24
# Adding 6 + 4
# Final result: 10π§ Function Parameters β
Think of parameters like settings on a washing machine - you can adjust them for different situations.
Default Parameters β
def greet(name, greeting="Hello", punctuation="!"):
"""Greet someone with customizable greeting and punctuation."""
message = f"{greeting}, {name}{punctuation}"
print(message)
return message
# Using defaults
greet("Alice")
# Overriding some defaults
greet("Bob", "Hi")
# Overriding all defaults
greet("Charlie", "Hey", "!!!")
# Expected output:
# Hello, Alice!
# Hi, Bob!
# Hey, Charlie!!!Keyword Arguments β
def describe_person(name, age, city, hobby="reading"):
"""Describe a person with their details."""
description = f"{name} is {age} years old, lives in {city}, and enjoys {hobby}"
print(description)
return description
# Positional arguments
describe_person("Alice", 25, "New York")
# Keyword arguments (order doesn't matter)
describe_person(city="Boston", name="Bob", age=30, hobby="cooking")
# Mixed arguments
describe_person("Charlie", age=35, city="Chicago")
# Expected output:
# Alice is 25 years old, lives in New York, and enjoys reading
# Bob is 30 years old, lives in Boston, and enjoys cooking
# Charlie is 35 years old, lives in Chicago, and enjoys readingVariable Arguments (*args) β
*Think of args like a shopping bag - you can put as many items as you want inside.
def sum_all(*numbers):
"""Sum any number of arguments."""
print(f"Received numbers: {numbers}")
total = 0
for number in numbers:
total += number
print(f"Sum: {total}")
return total
def find_maximum(*values):
"""Find the maximum value among any number of arguments."""
if not values:
return None
max_val = values[0]
for value in values:
if value > max_val:
max_val = value
print(f"Maximum of {values} is {max_val}")
return max_val
# Test with different numbers of arguments
sum_all(1, 2, 3)
sum_all(1, 2, 3, 4, 5)
sum_all(10, 20)
find_maximum(5, 2, 8, 1, 9)
find_maximum(100)
# Expected output:
# Received numbers: (1, 2, 3)
# Sum: 6
# Received numbers: (1, 2, 3, 4, 5)
# Sum: 15
# Received numbers: (10, 20)
# Sum: 30
# Maximum of (5, 2, 8, 1, 9) is 9
# Maximum of (100,) is 100Keyword Variable Arguments (**kwargs) β
**Think of kwargs like a form with multiple fields - you can pass any number of named pieces of information.
def print_info(**kwargs):
"""Print information passed as keyword arguments."""
print("Person Information:")
for key, value in kwargs.items():
print(f" {key}: {value}")
print() # Empty line for separation
def create_profile(name, **additional_info):
"""Create a user profile with required name and optional additional info."""
profile = {"name": name}
profile.update(additional_info)
print(f"Created profile for {name}:")
for key, value in profile.items():
print(f" {key}: {value}")
return profile
# Test kwargs
print_info(name="Alice", age=25, city="New York", hobby="photography")
print_info(username="bob123", email="bob@email.com", role="admin")
# Test mixed parameters
alice_profile = create_profile("Alice", age=25, city="Boston", job="Engineer")
# Expected output:
# Person Information:
# name: Alice
# age: 25
# city: New York
# hobby: photography
#
# Person Information:
# username: bob123
# email: bob@email.com
# role: admin
#
# Created profile for Alice:
# name: Alice
# age: 25
# city: Boston
# job: Engineerπ Function Scope β
Variable scope is like room access in a house - some variables are private to a room (local), while others are shared in common areas (global).
# Global variable (accessible everywhere)
global_message = "I'm accessible everywhere!"
def demonstrate_scope():
"""Show how variable scope works."""
# Local variable (only accessible inside this function)
local_message = "I'm only accessible inside this function!"
print("Inside function:")
print(f" Global: {global_message}")
print(f" Local: {local_message}")
def modify_global():
"""Show how to modify global variables."""
global global_message
old_message = global_message
global_message = "I've been modified!"
print(f"Changed global message from '{old_message}' to '{global_message}'")
# Test scope
print("Outside function:")
print(f" Global: {global_message}")
demonstrate_scope()
modify_global()
print("\nAfter modification:")
print(f" Global: {global_message}")
# Expected output:
# Outside function:
# Global: I'm accessible everywhere!
# Inside function:
# Global: I'm accessible everywhere!
# Local: I'm only accessible inside this function!
# Changed global message from 'I'm accessible everywhere!' to 'I've been modified!'
#
# After modification:
# Global: I've been modified!π― Lambda Functions β
Lambda functions are like shortcuts - they're quick, one-line functions for simple tasks.
Basic Lambda β
# Regular function
def square(x):
"""Square a number using a regular function."""
result = x ** 2
print(f"Square of {x} is {result}")
return result
# Lambda function (one-liner)
square_lambda = lambda x: x ** 2
# Test both approaches
print("Regular function:")
regular_result = square(5)
print("\nLambda function:")
lambda_result = square_lambda(5)
print(f"Lambda result: {lambda_result}")
# Expected output:
# Regular function:
# Square of 5 is 25
#
# Lambda function:
# Lambda result: 25Lambda with Multiple Arguments β
# Lambda functions with multiple parameters
add = lambda x, y: x + y
multiply = lambda x, y, z: x * y * z
greet = lambda name: f"Hello, {name}!"
print(f"Addition: {add(3, 5)}")
print(f"Multiplication: {multiply(2, 3, 4)}")
print(f"Greeting: {greet('Alice')}")
# Using lambda with built-in functions
numbers = [1, 2, 3, 4, 5]
print(f"Original numbers: {numbers}")
squared = list(map(lambda x: x**2, numbers))
print(f"Squared: {squared}")
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(f"Even numbers: {even_numbers}")
# Expected output:
# Addition: 8
# Multiplication: 24
# Greeting: Hello, Alice!
# Original numbers: [1, 2, 3, 4, 5]
# Squared: [1, 4, 9, 16, 25]
# Even numbers: [2, 4]π Practical Examples β
Example 1: Calculator Functions β
def calculator():
"""A simple calculator with multiple operations."""
def add(x, y):
result = x + y
print(f"{x} + {y} = {result}")
return result
def subtract(x, y):
result = x - y
print(f"{x} - {y} = {result}")
return result
def multiply(x, y):
result = x * y
print(f"{x} Γ {y} = {result}")
return result
def divide(x, y):
if y != 0:
result = x / y
print(f"{x} Γ· {y} = {result}")
return result
else:
print("Error: Cannot divide by zero!")
return None
# Test all operations
print("Calculator Demo:")
add(10, 5)
subtract(10, 5)
multiply(10, 5)
divide(10, 5)
divide(10, 0) # Test error handling
# Run calculator demo
calculator()
# Expected output:
# Calculator Demo:
# 10 + 5 = 15
# 10 - 5 = 5
# 10 Γ 5 = 50
# 10 Γ· 5 = 2.0
# Error: Cannot divide by zero!Example 2: Temperature Converter β
def temperature_converter():
"""Convert temperatures between Celsius and Fahrenheit."""
def celsius_to_fahrenheit(celsius):
fahrenheit = (celsius * 9/5) + 32
print(f"{celsius}Β°C = {fahrenheit}Β°F")
return fahrenheit
def fahrenheit_to_celsius(fahrenheit):
celsius = (fahrenheit - 32) * 5/9
print(f"{fahrenheit}Β°F = {celsius:.1f}Β°C")
return celsius
def convert_temperature(temp, from_scale):
"""Universal temperature converter."""
if from_scale.lower() == 'c':
return celsius_to_fahrenheit(temp)
elif from_scale.lower() == 'f':
return fahrenheit_to_celsius(temp)
else:
print(f"Error: Invalid scale '{from_scale}'. Use 'C' or 'F'.")
return None
# Test conversions
print("Temperature Converter Demo:")
convert_temperature(100, 'c') # Boiling point of water
convert_temperature(32, 'f') # Freezing point of water
convert_temperature(98.6, 'f') # Body temperature
convert_temperature(0, 'c') # Freezing point
convert_temperature(25, 'x') # Invalid scale
# Run temperature converter demo
temperature_converter()
# Expected output:
# Temperature Converter Demo:
# 100Β°C = 212.0Β°F
# 32Β°F = 0.0Β°C
# 98.6Β°F = 37.0Β°C
# 0Β°C = 32.0Β°F
# Error: Invalid scale 'x'. Use 'C' or 'F'.Example 3: Password Validator β
def create_password_validator():
"""Create a comprehensive password validation system."""
def check_length(password, min_length=8):
"""Check if password meets minimum length requirement."""
return len(password) >= min_length
def check_character_types(password):
"""Check for different character types in password."""
has_upper = any(c.isupper() for c in password)
has_lower = any(c.islower() for c in password)
has_digit = any(c.isdigit() for c in password)
has_special = any(c in "!@#$%^&*()_+-=[]{}|;:,.<>?" for c in password)
return has_upper, has_lower, has_digit, has_special
def validate_password(password):
"""Comprehensive password validation."""
print(f"Validating password: {'*' * len(password)}")
# Check length
if not check_length(password):
return False, "β Password must be at least 8 characters long"
# Check character types
has_upper, has_lower, has_digit, has_special = check_character_types(password)
issues = []
if not has_upper:
issues.append("uppercase letter")
if not has_lower:
issues.append("lowercase letter")
if not has_digit:
issues.append("digit")
if not has_special:
issues.append("special character")
if issues:
return False, f"β Password must contain: {', '.join(issues)}"
return True, "β
Password is strong and valid!"
# Test different passwords
test_passwords = [
"weak",
"weakpassword",
"WeakPassword",
"WeakPassword1",
"StrongPass123!",
"MySecure@Pass2024"
]
print("Password Validator Demo:")
for password in test_passwords:
is_valid, message = validate_password(password)
print(f" {message}")
print()
# Run password validator demo
create_password_validator()
# Expected output:
# Password Validator Demo:
# Validating password: ****
# β Password must be at least 8 characters long
#
# Validating password: ************
# β Password must contain: uppercase letter, digit, special character
#
# Validating password: ************
# β Password must contain: digit, special character
#
# Validating password: *************
# β Password must contain: special character
#
# Validating password: **************
# β
Password is strong and valid!
#
# Validating password: ******************
# β
Password is strong and valid!π Documentation with Docstrings β
Docstrings are like instruction manuals - they explain what your function does, what it needs, and what it returns.
def calculate_circle_properties(radius):
"""
Calculate various properties of a circle.
This function demonstrates proper docstring formatting
and comprehensive documentation practices.
Args:
radius (float): The radius of the circle in units
Returns:
dict: A dictionary containing:
- area (float): The area of the circle
- circumference (float): The circumference of the circle
- diameter (float): The diameter of the circle
Raises:
ValueError: If radius is negative
Example:
>>> properties = calculate_circle_properties(5)
>>> print(properties['area'])
78.54
"""
if radius < 0:
raise ValueError("Radius cannot be negative")
import math
properties = {
'radius': radius,
'diameter': 2 * radius,
'circumference': 2 * math.pi * radius,
'area': math.pi * radius ** 2
}
# Print results for demonstration
print(f"Circle with radius {radius}:")
for key, value in properties.items():
if isinstance(value, float):
print(f" {key}: {value:.2f}")
else:
print(f" {key}: {value}")
return properties
# Test the function
circle = calculate_circle_properties(5)
# Access the docstring
print("\nFunction documentation:")
print(calculate_circle_properties.__doc__)
# Expected output:
# Circle with radius 5:
# radius: 5
# diameter: 10
# circumference: 31.42
# area: 78.54
#
# Function documentation:
# [The full docstring would be displayed here]π Next Steps β
- Data Structures β Learn about lists, dictionaries, and more
- Loops β Master for loops and while loops for repetitive tasks
- Modules β Organize code into reusable modules and packages
- Object-Oriented Programming β Create classes and objects
Key Takeaways:
- Functions are reusable code blocks that make programs modular and organized
- Parameters make functions flexible; return values provide useful output
- Variable scope determines where variables can be accessed (local vs global)
- Lambda functions provide concise syntax for simple operations
- Docstrings document function behavior and make code maintainable
- Good function design follows the principle: one function, one purpose