Skip to content

Function Arguments in Detail

Mastering the Art of Parameter Passing


Parameter Types Overview

python
def function(
    pos1, pos2,              # Positional parameters
    default_arg=10,          # Default parameter
    *args,                   # Variable positional parameters
    kwonly_arg,              # Keyword-only parameter
    **kwargs                 # Variable keyword parameters
):
    pass

Positional vs Keyword Arguments

python
def describe_person(name, age, city):
    print(f"{name}, {age} years old, from {city}")

# Positional arguments (order matters)
describe_person("Alice", 25, "Beijing")

# Keyword arguments (order doesn't matter)
describe_person(city="Shanghai", name="Bob", age=30)

# Mixed (positional arguments must come first)
describe_person("Carol", age=28, city="Guangzhou")

Default Parameters

python
def calculate_income_tax(income, tax_rate=0.25):
    """Default tax rate 25%"""
    return income * tax_rate

print(calculate_income_tax(100000))         # 25000 (using default)
print(calculate_income_tax(100000, 0.30))   # 30000 (specified rate)

⚠️ Default Parameter Trap:

python
# ❌ Dangerous: Mutable object as default parameter
def add_student(name, courses=[]):
    courses.append(name)
    return courses

print(add_student("Alice"))  # ['Alice']
print(add_student("Bob"))    # ['Alice', 'Bob']  ← Sharing the same list!

# ✅ Correct approach
def add_student(name, courses=None):
    if courses is None:
        courses = []
    courses.append(name)
    return courses

Variable Arguments (*args)

python
def calculate_average(*scores):
    """Accept any number of scores"""
    if not scores:
        return 0
    return sum(scores) / len(scores)

print(calculate_average(85, 90, 78))           # 84.33
print(calculate_average(95, 88, 92, 76, 85))   # 87.2

# Unpacking a list
my_scores = [85, 90, 78, 92]
print(calculate_average(*my_scores))  # Using * to unpack

Practical Case: Merging Data

python
def merge_survey_data(*surveys):
    """Merge multiple survey datasets"""
    all_respondents = []
    for survey in surveys:
        all_respondents.extend(survey)
    return all_respondents

survey1 = [{"id": 1, "age": 25}, {"id": 2, "age": 30}]
survey2 = [{"id": 3, "age": 35}]
survey3 = [{"id": 4, "age": 40}, {"id": 5, "age": 45}]

all_data = merge_survey_data(survey1, survey2, survey3)
print(f"Total respondents: {len(all_data)} people")

Variable Keyword Arguments (**kwargs)

python
def create_respondent(**info):
    """Create respondent record"""
    return {
        'respondent_id': info.get('id', 0),
        'name': info.get('name', 'Unknown'),
        'age': info.get('age', 0),
        'additional_info': {k: v for k, v in info.items()
                           if k not in ['id', 'name', 'age']}
    }

# Flexible argument passing
resp = create_respondent(
    id=1001,
    name="Alice",
    age=30,
    income=75000,
    education="Master's",
    city="Beijing"
)
print(resp)

Unpacking Dictionary:

python
def register_student(name, age, major):
    print(f"{name}, {age} years old, {major}")

student_data = {'name': 'Alice', 'age': 25, 'major': 'Economics'}
register_student(**student_data)  # Unpack dictionary

Combined Usage

python
def process_survey_data(survey_name, year, *respondents, **metadata):
    """
    survey_name, year: Required positional parameters
    *respondents: Variable number of respondents
    **metadata: Additional metadata
    """
    print(f"=== {survey_name} ({year}) ===")
    print(f"Number of respondents: {len(respondents)}")
    print(f"Metadata: {metadata}")

    for i, resp in enumerate(respondents, 1):
        print(f"  {i}. {resp}")

# Usage
process_survey_data(
    "China Household Income Survey",
    2024,
    {"id": 1, "age": 30},
    {"id": 2, "age": 35},
    {"id": 3, "age": 40},
    region="National",
    sample_method="Stratified sampling",
    response_rate=0.85
)

Keyword-Only Parameters (Python 3+)

python
def calculate_tax(income, *, tax_rate, deduction=0):
    """
    income: Positional parameter
    *: Parameters after this must be passed as keywords
    tax_rate: Must use keyword
    deduction: Has default value, but must also use keyword
    """
    taxable = income - deduction
    return taxable * tax_rate

# ✅ Correct
result = calculate_tax(100000, tax_rate=0.25, deduction=10000)

# ❌ Wrong
# result = calculate_tax(100000, 0.25)  # TypeError

Why Use? Improves code readability, avoids parameter position errors.


Real-World: Data Analysis Function Library

python
def filter_data(data, *, min_age=None, max_age=None, gender=None, min_income=None):
    """Filter data (keyword-only parameters ensure clarity)"""
    filtered = data

    if min_age is not None:
        filtered = [r for r in filtered if r.get('age', 0) >= min_age]

    if max_age is not None:
        filtered = [r for r in filtered if r.get('age', 0) <= max_age]

    if gender is not None:
        filtered = [r for r in filtered if r.get('gender') == gender]

    if min_income is not None:
        filtered = [r for r in filtered if r.get('income', 0) >= min_income]

    return filtered

# Usage
respondents = [
    {'id': 1, 'age': 25, 'gender': 'Female', 'income': 50000},
    {'id': 2, 'age': 35, 'gender': 'Male', 'income': 80000},
    {'id': 3, 'age': 45, 'gender': 'Female', 'income': 95000},
]

# Clear filtering
young_females = filter_data(respondents, max_age=30, gender='Female')
high_earners = filter_data(respondents, min_income=70000)

Best Practices

1. Parameter Order

python
# Recommended order
def function(
    required_positional,      # Required positional parameters
    optional_positional=None, # Optional positional parameters
    *args,                    # Variable positional parameters
    required_keyword_only,    # Required keyword-only parameters
    optional_keyword=None,    # Optional keyword parameters
    **kwargs                  # Variable keyword parameters
):
    pass

2. When to Use Each Parameter Type

Parameter TypeUse Case
PositionalFew and obvious parameters (e.g., calculate_bmi(weight, height))
DefaultCommon default values (e.g., tax_rate=0.25)
*argsIndefinite number of similar parameters (e.g., sum(*numbers))
**kwargsFlexible configuration options
Keyword-onlyImprove readability, avoid confusion

3. Clear Function Signature

python
# ❌ Unclear
def process(a, b, c, d, e, f):
    pass

# ✅ Clear
def process_survey_response(
    respondent_id,
    age,
    gender,
    income,
    education,
    satisfaction_score
):
    pass

Practice Exercises

Exercise 1: Flexible Statistics Function

python
# Write function calculate_stats(*values, **options)
# values: Any number of values
# options: Optional parameters
#   - include_std: Whether to calculate standard deviation
#   - round_digits: Decimal places to keep

# Example
result = calculate_stats(1, 2, 3, 4, 5, include_std=True, round_digits=2)

Exercise 2: Data Filter

python
# Write function filter_respondents(data, **criteria)
# criteria can include: min_age, max_age, gender, education, city, etc.
# Return list of respondents matching all criteria

data = [
    {'id': 1, 'age': 25, 'gender': 'F', 'city': 'Beijing'},
    {'id': 2, 'age': 35, 'gender': 'M', 'city': 'Shanghai'},
    # ...
]

result = filter_respondents(data, min_age=30, city='Shanghai')

Next Steps

In the next section, we'll learn about Lambda functions and functional programming.

Continue!

Released under the MIT License. Content © Author.