Master the fundamentals of Python functions and learn how to create reusable, efficient code.
A function is a reusable block of code that performs a specific task. Functions help organize code, make it more readable, and allow for code reuse.
Think of functions like recipes in a cookbook. Each recipe (function) has a name, ingredients (parameters), and steps (code) to create something specific.
# Basic function definition
def greet(name):
"""Return a greeting message."""
return f"Hello, {name}!"
# Function call
message = greet("Alice")
print(message) # Output: Hello, Alice!
Functions in Python are defined using the 'def' keyword, followed by the function name, parameters in parentheses, and a colon.
The function definition creates a new function object and assigns it to the function name. The code inside the function only runs when the function is called.
def calculate_area(length, width):
"""
Calculate the area of a rectangle.
Args:
length (float): Length of the rectangle
width (float): Width of the rectangle
Returns:
float: Area of the rectangle
"""
return length * width
# Using the function
area = calculate_area(5, 3)
print(f"Area: {area}") # Output: Area: 15
Parameters are variables that receive values when a function is called. Python supports different types of parameters: required, default, and variable-length parameters.
Parameters make functions flexible and reusable. Required parameters must be provided, default parameters have preset values, and variable-length parameters can accept any number of arguments.
# Required parameters
def add(x, y):
return x + y
# Default parameters
def greet(name="Guest"):
return f"Hello, {name}!"
# Variable-length parameters
def sum_all(*args):
return sum(args)
# Using the functions
print(add(5, 3)) # Output: 8
print(greet()) # Output: Hello, Guest!
print(greet("Alice")) # Output: Hello, Alice!
print(sum_all(1, 2, 3, 4)) # Output: 10
The return statement sends a value back to the code that called the function. A function can return any type of data, including multiple values.
Return values allow functions to communicate their results back to the calling code. Functions can return single values, multiple values, or no value (None).
# Single return value
def square(number):
return number ** 2
# Multiple return values
def get_coordinates():
return 10, 20
# No return value
def print_message(message):
print(message)
# Returns None implicitly
# Using the functions
result = square(5)
print(result) # Output: 25
x, y = get_coordinates()
print(f"Coordinates: ({x}, {y})") # Output: Coordinates: (10, 20)
Docstrings are string literals that appear as the first statement in a function. They provide documentation about the function's purpose, parameters, and return values.
Good documentation helps other developers understand how to use your functions. Python's help() function and documentation generators use docstrings to create documentation.
def calculate_total(items, tax_rate=0.1):
"""
Calculate the total price including tax.
Args:
items (list): List of item prices
tax_rate (float): Tax rate as decimal (default: 0.1)
Returns:
float: Total price with tax
Raises:
ValueError: If tax_rate is negative
"""
if tax_rate < 0:
raise ValueError("Tax rate cannot be negative")
subtotal = sum(items)
tax = subtotal * tax_rate
return subtotal + tax
Scope refers to the visibility and lifetime of variables in a program. Python has local, global, and nonlocal scopes.
Variables defined inside a function are local to that function. Global variables are accessible throughout the program. The nonlocal keyword allows access to variables in the outer scope.
# Global variable
x = 10
def my_function():
# Local variable
y = 20
print(f"Inside function: x = {x}, y = {y}")
def modify_global():
global x
x = 30
print(f"Modified global x: {x}")
# Using the functions
my_function() # Output: Inside function: x = 10, y = 20
modify_global() # Output: Modified global x: 30
print(f"Global x: {x}") # Output: Global x: 30
Lambda functions are small anonymous functions that can have any number of arguments but can only have one expression.
Lambda functions are useful when you need a simple function for a short period of time. They're often used with built-in functions like map(), filter(), and sorted().
# Basic lambda function
square = lambda x: x ** 2
# Using lambda with map()
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
# Using lambda with filter()
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(squared) # Output: [1, 4, 9, 16, 25]
print(even_numbers) # Output: [2, 4]
Arguments are the values passed to a function when it is called. Python supports positional, keyword, default, and variable-length arguments.
Understanding different types of arguments helps you write more flexible and powerful functions. You can mix different types of arguments in a single function.
def create_profile(name, age, city="Unknown", **kwargs):
"""
Create a user profile with required and optional information.
Args:
name (str): User's name
age (int): User's age
city (str): User's city (optional)
**kwargs: Additional user information
"""
profile = {
"name": name,
"age": age,
"city": city,
**kwargs
}
return profile
# Using different types of arguments
profile1 = create_profile("Alice", 25)
profile2 = create_profile("Bob", 30, "New York", occupation="Developer")
print(profile1)
print(profile2)
Decorators are functions that modify the behavior of other functions. They provide a way to add functionality to existing functions without modifying their code.
Decorators are powerful tools for code reuse and separation of concerns. They're commonly used for logging, timing, access control, and caching.
def timer(func):
def wrapper(*args, **kwargs):
import time
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"Function {func.__name__} took {end - start} seconds")
return result
return wrapper
@timer
def slow_function():
import time
time.sleep(1)
return "Done!"
# Using the decorated function
result = slow_function() # Output: Function slow_function took 1.0 seconds
Good functions are well-documented, focused on a single task, and follow Python's style guidelines. They should be easy to understand, test, and maintain.
Following best practices helps create maintainable and reliable code. This includes proper naming, documentation, error handling, and code organization.
def calculate_statistics(numbers):
"""
Calculate basic statistics for a list of numbers.
Args:
numbers (list): List of numbers
Returns:
dict: Dictionary containing statistics
Raises:
ValueError: If the list is empty
"""
if not numbers:
raise ValueError("List cannot be empty")
return {
"count": len(numbers),
"sum": sum(numbers),
"average": sum(numbers) / len(numbers),
"minimum": min(numbers),
"maximum": max(numbers)
}
# Using the function
try:
stats = calculate_statistics([1, 2, 3, 4, 5])
print(stats)
except ValueError as e:
print(f"Error: {e}")