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
):
passPositional 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 coursesVariable 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 unpackPractical 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 dictionaryCombined 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) # TypeErrorWhy 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
):
pass2. When to Use Each Parameter Type
| Parameter Type | Use Case |
|---|---|
| Positional | Few and obvious parameters (e.g., calculate_bmi(weight, height)) |
| Default | Common default values (e.g., tax_rate=0.25) |
| *args | Indefinite number of similar parameters (e.g., sum(*numbers)) |
| **kwargs | Flexible configuration options |
| Keyword-only | Improve 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
):
passPractice 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!