🎛️ Function Parameters
Function parameters are the gateway for passing information into functions, making them flexible and reusable. Python offers several parameter types that handle different scenarios, from simple values to complex argument patterns that adapt to various calling styles.
# Different parameter types in action
def create_user_profile(name, age, city="Unknown", *interests, **settings):
"""Create a user profile with various parameter types"""
profile = {
'name': name, # Required positional
'age': age, # Required positional
'city': city, # Default parameter
'interests': interests, # Variable positional
'settings': settings # Variable keyword
}
return profile
# Multiple ways to call the function
profile1 = create_user_profile("Alice", 25)
profile2 = create_user_profile("Bob", 30, "Boston", "coding", "music")
profile3 = create_user_profile("Charlie", 28, notifications=True, theme="dark")
print("Profile 1:", profile1)
print("Profile 2:", profile2)
🎯 Positional Parameters
Positional parameters are the most common type, where arguments are matched to parameters based on their order. These create clear, predictable function interfaces for essential data.
def calculate_rectangle_area(length, width):
"""Calculate area using positional parameters"""
return length * width
def format_name(first, last, middle=""):
"""Format full name with optional middle name"""
if middle:
return f"{first} {middle} {last}"
return f"{first} {last}"
# Positional arguments must match parameter order
area = calculate_rectangle_area(10, 5)
name1 = format_name("John", "Smith")
name2 = format_name("Jane", "Doe", "Marie")
print(f"Area: {area}")
print(f"Name 1: {name1}")
print(f"Name 2: {name2}")
⚡ Keyword Parameters
Keyword parameters allow arguments to be passed by name rather than position, improving code readability and preventing errors when functions have many parameters.
def send_email(recipient, subject, body, priority="normal", html=False):
"""Send email with keyword parameters for clarity"""
email_info = {
'to': recipient,
'subject': subject,
'body': body,
'priority': priority,
'html_format': html
}
print(f"Sending email: {email_info}")
return "Email sent successfully"
# Keyword arguments for clarity
send_email(
recipient="user@example.com",
subject="Welcome!",
body="Thanks for joining us",
html=True
)
# Mix positional and keyword
send_email("admin@site.com", "Alert", "System status", priority="high")
🚀 Default Parameters
Default parameters provide fallback values when arguments aren't provided, making functions more flexible and reducing the need for multiple function definitions.
def create_database_connection(host="localhost", port=5432, username="admin", timeout=30):
"""Connect to database with sensible defaults"""
connection_string = f"postgresql://{username}@{host}:{port}?timeout={timeout}"
print(f"Connecting to: {connection_string}")
return connection_string
# Use all defaults
local_db = create_database_connection()
# Override specific parameters
prod_db = create_database_connection(host="prod.db.com", username="prod_user")
# Override multiple parameters
custom_db = create_database_connection("custom.db", 3306, "custom_user", 60)
print(f"Local: {local_db}")
print(f"Production: {prod_db}")
📊 Parameter Types Comparison Table
Parameter Type | Syntax | Required | Position Matters | Use Case |
---|---|---|---|---|
Positional | def func(a, b) | Yes | Yes | Essential arguments |
Keyword | Called with func(a=1, b=2) | Yes | No | Clear argument purpose |
Default | def func(a, b=10) | No | Position dependent | Optional configuration |
Variable Positional | def func(*args) | No | Yes | Unknown number of args |
Variable Keyword | def func(**kwargs) | No | No | Flexible options |
🌟 Variable-Length Arguments
Variable-length parameters handle situations where you don't know in advance how many arguments will be passed, providing flexibility for extensible function designs.
*args for Multiple Positional Arguments
The *args parameter collects extra positional arguments into a tuple, enabling functions that work with varying numbers of inputs.
def calculate_average(*numbers):
"""Calculate average of any number of values"""
if not numbers:
return 0
return sum(numbers) / len(numbers)
def log_message(level, *messages):
"""Log multiple messages with a specified level"""
timestamp = "2024-01-15 10:30:00"
all_messages = " | ".join(messages)
print(f"[{timestamp}] {level.upper()}: {all_messages}")
# Variable number of arguments
avg1 = calculate_average(10, 20, 30)
avg2 = calculate_average(5, 15, 25, 35, 45)
log_message("info", "User logged in", "Session started")
log_message("error", "Database connection failed", "Retrying", "Timeout after 30s")
print(f"Average 1: {avg1}")
print(f"Average 2: {avg2}")
**kwargs for Keyword Arguments
The **kwargs parameter captures extra keyword arguments as a dictionary, perfect for configuration options and extensible APIs.
def create_web_server(host, port, **config):
"""Create web server with flexible configuration"""
server_config = {
'host': host,
'port': port,
'debug': config.get('debug', False),
'ssl': config.get('ssl', False),
'workers': config.get('workers', 1)
}
print(f"Starting server on {host}:{port}")
for key, value in config.items():
print(f" {key}: {value}")
return server_config
# Flexible configuration options
dev_server = create_web_server("localhost", 3000, debug=True, hot_reload=True)
prod_server = create_web_server(
"0.0.0.0",
80,
ssl=True,
workers=4,
cache=True,
compression=True
)
💡 Combining Parameter Types
Real-world functions often combine different parameter types to create powerful, flexible interfaces that handle various calling patterns effectively.
def process_data(data, operation, *filters, output_format="json", **options):
"""Process data with flexible filtering and options"""
print(f"Processing {len(data)} items with {operation}")
# Apply filters
processed_data = data
for filter_func in filters:
print(f"Applying filter: {filter_func}")
# Handle options
if options.get('verbose', False):
print(f"Output format: {output_format}")
print(f"Additional options: {options}")
return f"Processed data in {output_format} format"
# Complex function call with mixed parameters
data_list = ["item1", "item2", "item3"]
result = process_data(
data_list, # Required positional
"transform", # Required positional
"filter1", "filter2", # Variable positional (*filters)
output_format="xml", # Keyword argument
verbose=True, # Additional keyword (**options)
sort=True,
limit=100
)
print(f"Result: {result}")
📚 Practical Applications
Configuration Functions
Parameter flexibility enables functions that adapt to different environments and requirements.
def deploy_application(app_name, *environments, replicas=1, **config):
"""Deploy application with flexible configuration"""
print(f"Deploying {app_name} to environments: {environments}")
print(f"Replicas: {replicas}")
for env in environments:
print(f" {env}: {config.get(f'{env}_config', 'default')}")
return f"Deployed {app_name} successfully"
# Flexible deployment calls
deploy_application("web-app", "staging", "production", replicas=3,
staging_config="debug", production_config="optimized")
API Wrappers
Functions with flexible parameters create clean interfaces for complex APIs.
def api_request(endpoint, method="GET", **params):
"""Make API request with flexible parameters"""
request_info = {
'endpoint': endpoint,
'method': method,
'params': params
}
print(f"API Request: {request_info}")
return f"Response from {endpoint}"
# Various API calls
response1 = api_request("/users", "GET", limit=10, page=1)
response2 = api_request("/users", "POST", name="John", email="john@example.com")
Hands-on Exercise
Create a function that introduces a person. It should take a required name parameter and an optional age parameter with a default value of 25.
def introduce_person(name, age=25):
# TODO: Create an introduction message using name and age
# TODO: Return the introduction message
pass
# TODO: Test with name only (should use default age)
intro1 = introduce_person("Alice")
print(intro1)
# TODO: Test with both name and age
intro2 = introduce_person("Bob", 30)
print(intro2)
Solution and Explanation 💡
Click to see the complete solution
def introduce_person(name, age=25):
# Create an introduction message using name and age
introduction = f"Hi, my name is {name} and I am {age} years old."
# Return the introduction message
return introduction
# Test with name only (should use default age)
intro1 = introduce_person("Alice")
print(intro1)
# Test with both name and age
intro2 = introduce_person("Bob", 30)
print(intro2)
Key Learning Points:
- 📌 Default parameters: Set default values with
parameter=value
in function definition - 📌 Required vs optional:
name
is required,age
is optional with default value 25 - 📌 Parameter order: Required parameters come before optional ones
- 📌 Calling options: Can call with just required params or override defaults
Learn more about returning values to master how functions communicate results back to your program.
Test Your Knowledge
Test what you've learned about function parameters:
What's Next?
Now that you understand how to pass data into functions, you're ready to learn how functions send data back. Understanding return values is essential for creating functions that provide useful results.
Ready to continue? Check out our lesson on Returning Values.
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.