Python functions are named blocks of code that execute when called. A Python function can accept input parameters, process data, and return output values. Functions in Python follow the DRY (Don’t Repeat Yourself) principle, allowing you to write code once and use it multiple times throughout your program.
The basic syntax for creating Python functions uses the def
keyword:
def function_name(parameters):
"""Optional docstring"""
# Function body
return value # Optional
Let’s create a simple Python function:
def greet_user(name):
"""This function greets a user by name"""
return f"Hello, {name}! Welcome to Python functions."
# Calling the function
message = greet_user("Alice")
print(message) # Output: Hello, Alice! Welcome to Python functions.
Python functions can accept different types of parameters, making them flexible and powerful.
Positional parameters are the most common type of parameters in Python functions:
def calculate_area(length, width):
"""Calculate rectangle area using positional parameters"""
return length * width
area = calculate_area(5, 3)
print(area) # Output: 15
Python functions support keyword arguments, allowing you to specify parameter names when calling the function:
def create_profile(name, age, city):
"""Create user profile with keyword arguments"""
return f"Name: {name}, Age: {age}, City: {city}"
profile = create_profile(city="New York", name="Bob", age=25)
print(profile) # Output: Name: Bob, Age: 25, City: New York
Python functions can have default parameter values, making some arguments optional:
def send_email(recipient, subject, body="Default message"):
"""Send email with optional body parameter"""
return f"To: {recipient}\nSubject: {subject}\nBody: {body}"
email1 = send_email("john@example.com", "Meeting")
email2 = send_email("jane@example.com", "Update", "Custom message")
Python functions can handle variable numbers of arguments using special syntax.
The *args
parameter allows Python functions to accept any number of positional arguments:
def sum_numbers(*args):
"""Sum any number of arguments using *args"""
total = 0
for number in args:
total += number
return total
result1 = sum_numbers(1, 2, 3) # Output: 6
result2 = sum_numbers(10, 20, 30, 40) # Output: 100
The **kwargs
parameter allows Python functions to accept any number of keyword arguments:
def build_car(**kwargs):
"""Build car specification using **kwargs"""
car_info = "Car Specifications:\n"
for key, value in kwargs.items():
car_info += f"{key}: {value}\n"
return car_info
car = build_car(brand="Toyota", model="Camry", year=2023, color="Blue")
print(car)
Python functions can return values using the return
statement. Functions can return single values, multiple values, or no value at all.
def calculate_square(number):
"""Return square of a number"""
return number ** 2
square = calculate_square(4)
print(square) # Output: 16
Python functions can return multiple values as tuples:
def get_name_parts(full_name):
"""Split full name into first and last name"""
parts = full_name.split()
first_name = parts[0]
last_name = parts[-1]
return first_name, last_name
first, last = get_name_parts("John Smith")
print(f"First: {first}, Last: {last}") # Output: First: John, Last: Smith
Understanding variable scope is crucial when working with Python functions.
Variables defined inside Python functions are local and only accessible within that function:
def calculate_discount():
"""Demonstrate local variable scope"""
discount_rate = 0.1 # Local variable
return discount_rate
def apply_discount(price):
"""Apply discount to price"""
local_discount = 0.15 # Local variable
return price * (1 - local_discount)
Global variables can be accessed from anywhere in the program:
tax_rate = 0.08 # Global variable
def calculate_total(price):
"""Calculate total price including tax"""
return price * (1 + tax_rate)
total = calculate_total(100)
print(total) # Output: 108.0
Lambda functions are anonymous Python functions that can be defined in a single line:
# Regular function
def multiply_by_two(x):
return x * 2
# Lambda function
multiply_lambda = lambda x: x * 2
# Using lambda with map()
numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, numbers))
print(doubled) # Output: [2, 4, 6, 8, 10]
Python functions can accept other functions as parameters or return functions as results.
def apply_operation(numbers, operation):
"""Apply operation function to list of numbers"""
return [operation(num) for num in numbers]
def square(x):
return x ** 2
def cube(x):
return x ** 3
numbers = [1, 2, 3, 4]
squares = apply_operation(numbers, square)
cubes = apply_operation(numbers, cube)
def create_multiplier(factor):
"""Return a function that multiplies by factor"""
def multiplier(number):
return number * factor
return multiplier
double = create_multiplier(2)
triple = create_multiplier(3)
print(double(5)) # Output: 10
print(triple(5)) # Output: 15
Recursive Python functions call themselves to solve problems by breaking them into smaller subproblems:
def factorial(n):
"""Calculate factorial using recursion"""
if n <= 1:
return 1
else:
return n * factorial(n - 1)
def fibonacci(n):
"""Calculate Fibonacci number using recursion"""
if n <= 1:
return n
else:
return fibonacci(n - 1) + fibonacci(n - 2)
print(factorial(5)) # Output: 120
print(fibonacci(6)) # Output: 8
Decorators modify or extend the behavior of Python functions without changing their code:
def timer_decorator(func):
"""Decorator to measure function execution time"""
import time
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time:.4f} seconds")
return result
return wrapper
@timer_decorator
def slow_function():
"""Function with timer decorator"""
import time
time.sleep(1)
return "Function completed"
result = slow_function()
Python provides many built-in functions that you can use directly:
# Common built-in functions
numbers = [1, 2, 3, 4, 5]
print(len(numbers)) # Output: 5
print(max(numbers)) # Output: 5
print(min(numbers)) # Output: 1
print(sum(numbers)) # Output: 15
print(sorted(numbers, reverse=True)) # Output: [5, 4, 3, 2, 1]
# Type conversion functions
print(str(123)) # Output: "123"
print(int("456")) # Output: 456
print(float("7.89")) # Output: 7.89
Here’s a comprehensive example demonstrating various Python function concepts:
import math
from functools import reduce
# Global configuration
DEFAULT_CURRENCY = "USD"
TAX_RATES = {"USD": 0.08, "EUR": 0.20, "GBP": 0.15}
def calculate_circle_properties(radius):
"""Calculate circle area and circumference"""
area = math.pi * radius ** 2
circumference = 2 * math.pi * radius
return area, circumference
def format_price(amount, currency=DEFAULT_CURRENCY):
"""Format price with currency symbol"""
symbols = {"USD": "$", "EUR": "€", "GBP": "£"}
return f"{symbols.get(currency, '$')}{amount:.2f}"
def apply_discount(price, discount_percent=0):
"""Apply discount to price"""
if discount_percent < 0 or discount_percent > 100:
raise ValueError("Discount must be between 0 and 100")
return price * (1 - discount_percent / 100)
def calculate_tax(price, currency=DEFAULT_CURRENCY):
"""Calculate tax based on currency"""
tax_rate = TAX_RATES.get(currency, 0.08)
return price * tax_rate
def process_order(*items, currency=DEFAULT_CURRENCY, discount=0, **customer_info):
"""Process order with multiple items and customer information"""
print(f"Processing order for {customer_info.get('name', 'Anonymous')}")
print(f"Email: {customer_info.get('email', 'Not provided')}")
print(f"Currency: {currency}")
print("-" * 40)
total = 0
for item in items:
item_name, price = item
discounted_price = apply_discount(price, discount)
tax = calculate_tax(discounted_price, currency)
final_price = discounted_price + tax
total += final_price
print(f"Item: {item_name}")
print(f" Original Price: {format_price(price, currency)}")
print(f" After Discount: {format_price(discounted_price, currency)}")
print(f" Tax: {format_price(tax, currency)}")
print(f" Final Price: {format_price(final_price, currency)}")
print()
print(f"Total Order Amount: {format_price(total, currency)}")
return total
# Lambda function for quick calculations
calculate_compound_interest = lambda principal, rate, time: principal * (1 + rate) ** time
# Higher-order function
def apply_to_prices(prices, operation):
"""Apply operation to list of prices"""
return list(map(operation, prices))
# Recursive function
def calculate_fibonacci_series(n, memo={}):
"""Calculate Fibonacci series with memoization"""
if n in memo:
return memo[n]
if n <= 1:
return n
memo[n] = calculate_fibonacci_series(n-1, memo) + calculate_fibonacci_series(n-2, memo)
return memo[n]
# Decorator function
def validate_positive(func):
"""Decorator to validate positive numbers"""
def wrapper(value):
if value <= 0:
raise ValueError("Value must be positive")
return func(value)
return wrapper
@validate_positive
def calculate_square_root(number):
"""Calculate square root of positive number"""
return math.sqrt(number)
# Main execution
if __name__ == "__main__":
# Test basic functions
print("=== Circle Properties ===")
area, circumference = calculate_circle_properties(5)
print(f"Circle with radius 5:")
print(f"Area: {area:.2f}")
print(f"Circumference: {circumference:.2f}")
print()
# Test order processing
print("=== Order Processing ===")
order_items = [
("Laptop", 999.99),
("Mouse", 29.99),
("Keyboard", 79.99)
]
total = process_order(
*order_items,
currency="USD",
discount=10,
name="John Doe",
email="john@example.com",
phone="123-456-7890"
)
print()
print("=== Lambda Function Example ===")
investment = calculate_compound_interest(1000, 0.05, 5)
print(f"$1000 invested at 5% for 5 years: ${investment:.2f}")
print()
print("=== Higher-Order Function Example ===")
prices = [10.99, 25.50, 99.99]
discounted_prices = apply_to_prices(prices, lambda x: x * 0.9)
print(f"Original prices: {prices}")
print(f"10% discount applied: {discounted_prices}")
print()
print("=== Recursive Function Example ===")
fib_series = [calculate_fibonacci_series(i) for i in range(10)]
print(f"First 10 Fibonacci numbers: {fib_series}")
print()
print("=== Decorator Example ===")
try:
sqrt_result = calculate_square_root(16)
print(f"Square root of 16: {sqrt_result}")
# This will raise an error due to decorator validation
# sqrt_negative = calculate_square_root(-1)
except ValueError as e:
print(f"Error: {e}")
print()
print("=== Built-in Functions Example ===")
numbers = [45, 23, 78, 12, 56, 89, 34]
print(f"Numbers: {numbers}")
print(f"Length: {len(numbers)}")
print(f"Maximum: {max(numbers)}")
print(f"Minimum: {min(numbers)}")
print(f"Sum: {sum(numbers)}")
print(f"Average: {sum(numbers) / len(numbers):.2f}")
print(f"Sorted: {sorted(numbers)}")
# Using reduce from functools
product = reduce(lambda x, y: x * y, [1, 2, 3, 4, 5])
print(f"Product of [1,2,3,4,5]: {product}")
Expected Output:
=== Circle Properties ===
Circle with radius 5:
Area: 78.54
Circumference: 31.42
=== Order Processing ===
Processing order for John Doe
Email: john@example.com
Currency: USD
----------------------------------------
Item: Laptop
Original Price: $999.99
After Discount: $899.99
Tax: $72.00
Final Price: $971.99
Item: Mouse
Original Price: $29.99
After Discount: $26.99
Tax: $2.16
Final Price: $29.15
Item: Keyboard
Original Price: $79.99
After Discount: $71.99
Tax: $5.76
Final Price: $77.75
Total Order Amount: $1078.89
=== Lambda Function Example ===
$1000 invested at 5% for 5 years: $1276.28
=== Higher-Order Function Example ===
Original prices: [10.99, 25.5, 99.99]
10% discount applied: [9.891, 22.95, 89.991]
=== Recursive Function Example ===
First 10 Fibonacci numbers: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
=== Decorator Example ===
Square root of 16: 4.0
=== Built-in Functions Example ===
Numbers: [45, 23, 78, 12, 56, 89, 34]
Length: 7
Maximum: 89
Minimum: 12
Sum: 337
Average: 48.14
Sorted: [12, 23, 34, 45, 56, 78, 89]
Product of [1,2,3,4,5]: 120
Python functions are fundamental building blocks that make your code more organized, reusable, and maintainable. Whether you’re using basic functions, advanced features like decorators, or built-in functions, mastering Python functions will significantly improve your programming skills. Practice creating different types of Python functions to become proficient in this essential programming concept.