🔗 Using *args and **kwargs
*args and **kwargs allow functions to accept variable numbers of arguments, making your functions more flexible and reusable. They're essential for creating functions that can handle different numbers of inputs.
# Function with *args (variable positional arguments)
def sum_numbers(*args):
total = 0
for number in args:
total += number
return total
# Function with **kwargs (variable keyword arguments)
def create_profile(**kwargs):
profile = {}
for key, value in kwargs.items():
profile[key] = value
return profile
# Using the functions
result1 = sum_numbers(1, 2, 3)
result2 = sum_numbers(10, 20, 30, 40, 50)
profile1 = create_profile(name="Alice", age=30)
profile2 = create_profile(name="Bob", age=25, city="New York")
print(f"Sum1: {result1}") # Sum1: 6
print(f"Sum2: {result2}") # Sum2: 150
print(f"Profile1: {profile1}")
print(f"Profile2: {profile2}")
🎯 Understanding *args and **kwargs
These special parameters allow functions to accept variable numbers of arguments.
Basic *args Usage
# Simple *args example
def greet_all(*names):
for name in names:
print(f"Hello, {name}!")
def find_maximum(*numbers):
if not numbers:
return None
return max(numbers)
def concatenate_strings(*strings):
return " ".join(strings)
# Test the functions
greet_all("Alice", "Bob", "Charlie")
max_num = find_maximum(5, 2, 9, 1, 7)
message = concatenate_strings("Python", "is", "awesome")
print(f"Maximum: {max_num}") # Maximum: 9
print(f"Message: {message}") # Message: Python is awesome
Basic **kwargs Usage
# Simple **kwargs example
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
def create_config(**settings):
config = {
"debug": False,
"timeout": 30
}
# Update with provided settings
config.update(settings)
return config
# Test the functions
print("User Information:")
print_info(name="Alice", age=30, city="Boston")
config = create_config(debug=True, timeout=60, host="localhost")
print(f"\nConfig: {config}")
Combining Regular Parameters with *args
# Regular parameters + *args
def calculate_total(tax_rate, *prices):
subtotal = sum(prices)
tax = subtotal * tax_rate
total = subtotal + tax
return total
def format_message(template, *values):
try:
return template.format(*values)
except IndexError:
return "Not enough values for template"
# Test the functions
total = calculate_total(0.08, 10, 20, 30) # tax_rate=0.08, prices=(10,20,30)
msg = format_message("Hello {}, you have {} messages", "Alice", 5)
print(f"Total with tax: ${total:.2f}") # Total with tax: $64.80
print(f"Message: {msg}") # Message: Hello Alice, you have 5 messages
📋 *args and **kwargs Reference
Syntax | Purpose | Example Usage |
---|---|---|
*args | Variable positional args | func(1, 2, 3) |
**kwargs | Variable keyword args | func(a=1, b=2) |
Both | Maximum flexibility | func(1, 2, a=3, b=4) |
🔧 Practical Examples
Function with All Parameter Types
def flexible_function(required, default="default", *args, **kwargs):
print(f"Required: {required}")
print(f"Default: {default}")
print(f"Extra args: {args}")
print(f"Keyword args: {kwargs}")
# Different ways to call the function
print("Call 1:")
flexible_function("must_have")
print("\nCall 2:")
flexible_function("must_have", "custom", 1, 2, 3)
print("\nCall 3:")
flexible_function("must_have", extra1="value1", extra2="value2")
print("\nCall 4:")
flexible_function("must_have", "custom", 1, 2, name="Alice", age=30)
Passing Arguments to Other Functions
def log_message(level, message):
print(f"[{level}] {message}")
def enhanced_log(*args, **kwargs):
# Add timestamp to kwargs
import datetime
kwargs["timestamp"] = datetime.datetime.now().strftime("%H:%M:%S")
# Call original function with passed arguments
log_message(*args)
# Print additional info
for key, value in kwargs.items():
print(f" {key}: {value}")
# Test the enhanced function
enhanced_log("INFO", "Application started", user="admin", version="1.0")
Building Flexible Data Structures
def create_user(name, email, **additional_info):
user = {
"name": name,
"email": email,
"active": True
}
# Add any additional information
user.update(additional_info)
return user
def format_list(*items, separator=", ", prefix="", suffix=""):
formatted_items = [f"{prefix}{item}{suffix}" for item in items]
return separator.join(formatted_items)
# Test the functions
user1 = create_user("Alice", "alice@email.com", age=30, city="Boston")
user2 = create_user("Bob", "bob@email.com", department="Engineering")
list1 = format_list("apple", "banana", "orange")
list2 = format_list("item1", "item2", "item3", separator=" | ", prefix=">> ")
print(f"User1: {user1}")
print(f"User2: {user2}")
print(f"List1: {list1}")
print(f"List2: {list2}")
📊 Parameter Order Reference
Position | Parameter Type | Example |
---|---|---|
1 | Required parameters | def func(a, b): |
2 | Default parameters | def func(a, b=10): |
3 | *args | def func(a, b=10, *args): |
4 | **kwargs | def func(a, b=10, *args, **kwargs): |
🔄 Unpacking Arguments
Unpacking Lists and Tuples with *
def add_three_numbers(a, b, c):
return a + b + c
# Unpack list/tuple when calling function
numbers = [1, 2, 3]
tuple_numbers = (10, 20, 30)
result1 = add_three_numbers(*numbers) # Same as add_three_numbers(1, 2, 3)
result2 = add_three_numbers(*tuple_numbers) # Same as add_three_numbers(10, 20, 30)
print(f"Result1: {result1}") # Result1: 6
print(f"Result2: {result2}") # Result2: 60
Unpacking Dictionaries with **
def create_account(username, email, active=True):
return {
"username": username,
"email": email,
"active": active
}
# Unpack dictionary when calling function
user_data = {
"username": "alice123",
"email": "alice@example.com",
"active": False
}
account = create_account(**user_data) # Same as create_account(username="alice123", ...)
print(f"Account: {account}")
🎯 Key Takeaways
🚀 What's Next?
Learn how to create decorators to enhance and modify function behavior.
Continue to: Create Decorators
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.