Python Functions and Modules
Functions are reusable blocks of code that perform specific tasks. Modules are files that contain Python code, including functions, classes, and variables. This tutorial covers how to create and use functions and modules in Python.
Python Functions
1. Defining Basic Functions
# Simple function
def greet():
print("Hello, World!")
# Function with parameters
def greet_person(name):
print(f"Hello, {name}!")
# Function with return value
def add_numbers(a, b):
return a + b
# Function with default parameters
def greet_with_title(name, title="Mr."):
return f"Hello, {title} {name}!"
# Calling functions
greet() # Output: Hello, World!
greet_person("Alice") # Output: Hello, Alice!
result = add_numbers(5, 3) # result = 8
print(greet_with_title("Smith")) # Output: Hello, Mr. Smith!
print(greet_with_title("Johnson", "Dr.")) # Output: Hello, Dr. Johnson!2. Function Parameters
# Positional parameters
def describe_person(name, age, city):
return f"{name} is {age} years old and lives in {city}."
# Keyword arguments
def create_profile(name, age, city="Unknown", country="USA"):
return {
"name": name,
"age": age,
"city": city,
"country": country
}
# Variable number of arguments
def sum_all(*numbers):
total = 0
for num in numbers:
total += num
return total
# Variable keyword arguments
def build_profile(**kwargs):
profile = {}
for key, value in kwargs.items():
profile[key] = value
return profile
# Examples
print(describe_person("John", 30, "New York"))
print(create_profile("Alice", 25, city="Boston"))
print(sum_all(1, 2, 3, 4, 5))
print(build_profile(name="Bob", age=35, city="Chicago", hobby="Photography"))3. Return Values
# Multiple return values
def get_coordinates():
x = 10
y = 20
return x, y # Returns a tuple
# Conditional return
def check_age(age):
if age >= 18:
return "Adult"
elif age >= 13:
return "Teenager"
else:
return "Child"
# Return different types
def analyze_number(num):
if num > 0:
return "Positive"
elif num < 0:
return "Negative"
else:
return 0 # Return integer
# Examples
x, y = get_coordinates()
print(f"Coordinates: x={x}, y={y}") # Output: Coordinates: x=10, y=20
print(check_age(25)) # Output: Adult
print(analyze_number(-5)) # Output: Negative4. Function Scope
# Global and local variables
x = "global"
def test_scope():
x = "local" # Local variable
print(f"Inside function: {x}")
def modify_global():
global x # Modify global variable
x = "modified global"
print(f"Modified global: {x}")
# Examples
print(f"Before function: {x}") # Output: global
test_scope() # Output: local
print(f"After function: {x}") # Output: global
modify_global() # Output: modified global
print(f"After modification: {x}") # Output: modified global5. Lambda Functions
# Simple lambda functions
square = lambda x: x ** 2
add = lambda x, y: x + y
# Lambda with conditional
is_even = lambda x: x % 2 == 0
# Lambda in built-in functions
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
squared_numbers = list(map(lambda x: x ** 2, numbers))
# Examples
print(square(5)) # Output: 25
print(add(3, 4)) # Output: 7
print(is_even(4)) # Output: True
print(even_numbers) # Output: [2, 4, 6, 8, 10]
print(squared_numbers) # Output: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]Python Modules
1. Creating Modules
Create a file named math_utils.py:
# math_utils.py
PI = 3.14159
def add(a, b):
"""Add two numbers."""
return a + b
def subtract(a, b):
"""Subtract two numbers."""
return a - b
def multiply(a, b):
"""Multiply two numbers."""
return a * b
def divide(a, b):
"""Divide two numbers."""
if b != 0:
return a / b
else:
return "Cannot divide by zero"
def circle_area(radius):
"""Calculate area of a circle."""
return PI * radius ** 2
class Calculator:
"""Simple calculator class."""
def __init__(self):
self.result = 0
def add(self, number):
self.result += number
return self.result
def subtract(self, number):
self.result -= number
return self.result
def reset(self):
self.result = 0
return self.result2. Importing Modules
# Import entire module
import math_utils
# Use module functions
result = math_utils.add(5, 3)
area = math_utils.circle_area(10)
print(f"Result: {result}, Area: {area}")
# Import specific functions
from math_utils import add, multiply, PI
result = add(5, 3)
product = multiply(4, 5)
print(f"PI: {PI}, Result: {result}, Product: {product}")
# Import with alias
import math_utils as math
result = math.add(10, 5)
print(f"Result: {result}")
# Import all (use with caution)
from math_utils import *
result = add(20, 10)
calc = Calculator()
print(f"Result: {result}, Calculator result: {calc.add(5)}")3. Standard Library Modules
# Math module
import math
print(f"Square root of 16: {math.sqrt(16)}")
print(f"Value of pi: {math.pi}")
print(f"Ceiling of 3.2: {math.ceil(3.2)}")
# Random module
import random
numbers = [1, 2, 3, 4, 5]
print(f"Random number: {random.randint(1, 100)}")
print(f"Random choice: {random.choice(numbers)}")
random.shuffle(numbers)
print(f"Shuffled list: {numbers}")
# Datetime module
from datetime import datetime, date, timedelta
now = datetime.now()
today = date.today()
future = now + timedelta(days=30)
print(f"Current time: {now}")
print(f"Today's date: {today}")
print(f"30 days from now: {future}")
# OS module
import os
print(f"Current directory: {os.getcwd()}")
print(f"List files: {os.listdir('.')}")
# JSON module
import json
data = {"name": "John", "age": 30, "city": "New York"}
json_string = json.dumps(data)
parsed_data = json.loads(json_string)
print(f"JSON string: {json_string}")
print(f"Parsed data: {parsed_data}")Advanced Function Concepts
1. Decorators
# Simple decorator
def uppercase_decorator(func):
def wrapper():
result = func()
return result.upper()
return wrapper
@uppercase_decorator
def greet():
return "hello, world!"
print(greet()) # Output: HELLO, WORLD!
# Decorator with parameters
def timer_decorator(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"Function {func.__name__} took {end - start:.4f} seconds")
return result
return wrapper
@timer_decorator
def slow_function():
import time
time.sleep(1)
return "Done!"
print(slow_function())2. Generators
# Generator function
def count_up_to(n):
count = 1
while count <= n:
yield count
count += 1
# Using generator
for number in count_up_to(5):
print(number) # Output: 1, 2, 3, 4, 5
# Generator expression
squares = (x ** 2 for x in range(10))
for square in squares:
print(square) # Output: 0, 1, 4, 9, 16, 25, 36, 49, 64, 81
# Practical example - reading large files
def read_large_file(file_path):
with open(file_path, 'r') as file:
for line in file:
yield line.strip()
# Usage (would process file line by line without loading all into memory)
# for line in read_large_file("large_file.txt"):
# print(line)3. Recursion
# Recursive factorial
def factorial(n):
if n <= 1:
return 1
else:
return n * factorial(n - 1)
# Recursive Fibonacci
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n - 1) + fibonacci(n - 2)
# Recursive directory listing
import os
def list_files(directory):
files = []
try:
for item in os.listdir(directory):
full_path = os.path.join(directory, item)
if os.path.isfile(full_path):
files.append(full_path)
elif os.path.isdir(full_path):
files.extend(list_files(full_path))
except PermissionError:
pass
return files
# Examples
print(f"Factorial of 5: {factorial(5)}")
print(f"Fibonacci of 7: {fibonacci(7)}")
# print(f"Files in current directory: {list_files('.')}")Module Organization
1. Package Structure
Create a package structure:
my_package/
├── __init__.py
├── module1.py
├── module2.py
└── subpackage/
├── __init__.py
└── module3.pymy_package/__init__.py:
# Package initialization
from .module1 import function1
from .module2 import function2
__version__ = "1.0.0"
__all__ = ["function1", "function2"]my_package/module1.py:
def function1():
return "Function 1 from module 1"
class Class1:
def method(self):
return "Method from Class 1"my_package/module2.py:
def function2():
return "Function 2 from module 2"
CONSTANT = "This is a constant from module 2"2. Using Packages
# Import from package
from my_package import function1, function2
from my_package.module1 import Class1
# Use imported items
print(function1())
print(function2())
obj = Class1()
print(obj.method())
# Import subpackage
from my_package.subpackage.module3 import function3Error Handling in Functions
1. Try-Except Blocks
def safe_divide(a, b):
try:
result = a / b
return result
except ZeroDivisionError:
return "Cannot divide by zero"
except TypeError:
return "Invalid input types"
except Exception as e:
return f"Unexpected error: {e}"
def read_file(filename):
try:
with open(filename, 'r') as file:
content = file.read()
return content
except FileNotFoundError:
return f"File {filename} not found"
except PermissionError:
return f"Permission denied for file {filename}"
except Exception as e:
return f"Error reading file: {e}"
# Examples
print(safe_divide(10, 2)) # Output: 5.0
print(safe_divide(10, 0)) # Output: Cannot divide by zero
print(safe_divide(10, "a")) # Output: Invalid input types2. Raising Exceptions
def validate_age(age):
if not isinstance(age, (int, float)):
raise TypeError("Age must be a number")
if age < 0:
raise ValueError("Age cannot be negative")
if age > 150:
raise ValueError("Age seems unrealistic")
return True
def process_user_data(name, age):
try:
validate_age(age)
return f"User {name} with age {age} is valid"
except (TypeError, ValueError) as e:
return f"Invalid data: {e}"
# Examples
print(process_user_data("John", 25)) # Valid
print(process_user_data("Jane", -5)) # Invalid age
print(process_user_data("Bob", "twenty")) # Invalid typeBest Practices
1. Function Design
# Good function design
def calculate_compound_interest(principal, rate, time, compounds_per_year=1):
"""
Calculate compound interest.
Args:
principal (float): Initial amount of money
rate (float): Annual interest rate (as decimal)
time (float): Time period in years
compounds_per_year (int): Number of times interest is compounded per year
Returns:
float: Final amount after compound interest
Raises:
ValueError: If any parameter is negative
"""
if principal < 0 or rate < 0 or time < 0:
raise ValueError("Parameters cannot be negative")
amount = principal * (1 + rate / compounds_per_year) ** (compounds_per_year * time)
return amount
# Usage
final_amount = calculate_compound_interest(1000, 0.05, 5, 12)
print(f"Final amount: ${final_amount:.2f}")2. Module Organization
# utils.py - Utility functions
def format_currency(amount, currency="$"):
"""Format amount as currency."""
return f"{currency}{amount:.2f}"
def validate_email(email):
"""Simple email validation."""
import re
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(pattern, email) is not None
# constants.py - Application constants
APP_NAME = "My Application"
VERSION = "1.0.0"
MAX_USERS = 1000
# config.py - Configuration settings
import os
DEBUG = os.getenv("DEBUG", "False").lower() == "true"
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///app.db")
SECRET_KEY = os.getenv("SECRET_KEY", "default-secret-key")3. Documentation
def process_data(data, options=None):
"""
Process input data according to specified options.
This function takes raw data and processes it based on the provided
options. It supports various data formats and processing methods.
Args:
data (list or dict): Input data to be processed
options (dict, optional): Processing options. Defaults to None.
- 'method' (str): Processing method ('clean', 'transform', 'analyze')
- 'output_format' (str): Output format ('json', 'csv', 'dict')
- 'verbose' (bool): Enable verbose output
Returns:
dict: Processed data with metadata
Raises:
TypeError: If data is not list or dict
ValueError: If invalid options are provided
Example:
>>> data = [1, 2, 3, 4, 5]
>>> options = {'method': 'clean', 'output_format': 'json'}
>>> result = process_data(data, options)
>>> print(result['status'])
'success'
"""
if not isinstance(data, (list, dict)):
raise TypeError("Data must be list or dict")
# Default options
default_options = {
'method': 'clean',
'output_format': 'dict',
'verbose': False
}
if options:
default_options.update(options)
# Processing logic here
result = {
'status': 'success',
'data': data,
'options': default_options,
'processed_at': str(datetime.now())
}
return resultExternal Resources:
Related Tutorials:
Last updated on