🎛️ 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 TypeSyntaxRequiredPosition MattersUse Case
Positionaldef func(a, b)YesYesEssential arguments
KeywordCalled with func(a=1, b=2)YesNoClear argument purpose
Defaultdef func(a, b=10)NoPosition dependentOptional configuration
Variable Positionaldef func(*args)NoYesUnknown number of args
Variable Keyworddef func(**kwargs)NoNoFlexible 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.

python
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?

😔Poor
🙁Fair
😊Good
😄Great
🤩Excellent