Lesson 9.3: Default and Keyword Arguments
What You'll Learn
- How to set default values for parameters
- How to use keyword arguments for clearer function calls
- How to mix positional and keyword arguments
- An introduction to
*argsfor variable positional arguments - An introduction to
**kwargsfor variable keyword arguments
1. Default Parameter Values
You can give parameters a default value so they become optional when calling the function:
def greet(name, greeting="Hello"): """Greet someone with a customizable greeting.""" print(f"{greeting}, {name}!") # Using the default greeting greet("Alice") # Overriding the default greet("Bob", "Hi") greet("Carol", "Good morning")
Hello, Alice!
Hi, Bob!
Good morning, Carol!
Rule: Parameters with default values must come after parameters without defaults.
def func(a=1, b) is a syntax error, but def func(a, b=1) is fine.
def power(base, exponent=2): """Raise base to exponent. Defaults to squaring.""" return base ** exponent print(power(5)) # 5^2 = 25 print(power(5, 3)) # 5^3 = 125 print(power(2, 10)) # 2^10 = 1024
25
125
1024
2. Keyword Arguments
Instead of relying on position, you can name the arguments when calling a function:
def describe_pet(animal, name, age): """Describe a pet.""" print(f"{name} is a {age}-year-old {animal}.") # Positional (order matters) describe_pet("dog", "Rex", 5) # Keyword (order doesn't matter) describe_pet(name="Whiskers", age=3, animal="cat") # Mix: positional first, then keyword describe_pet("bird", name="Tweety", age=2)
Rex is a 5-year-old dog.
Whiskers is a 3-year-old cat.
Tweety is a 2-year-old bird.
Keyword Arguments: Arguments passed using the
name=value syntax. They make function calls clearer and allow you to pass arguments in any order.
Rule: Positional arguments must come before keyword arguments in a function call.
func(name="A", "dog") is an error.
3. Combining Defaults and Keywords
Default values and keyword arguments work together to create flexible functions:
def create_profile(name, age, city="Unknown", hobby="Unknown"): """Create a profile string.""" return f"{name}, {age}, from {city}, enjoys {hobby}" # All defaults print(create_profile("Alice", 25)) # Override just one default print(create_profile("Bob", 30, city="LA")) # Override a later default without changing earlier ones print(create_profile("Carol", 28, hobby="painting")) # Override all defaults print(create_profile("Dave", 35, "NYC", "chess"))
Alice, 25, from Unknown, enjoys Unknown
Bob, 30, from LA, enjoys Unknown
Carol, 28, from Unknown, enjoys painting
Dave, 35, from NYC, enjoys chess
4. *args: Variable Positional Arguments
Sometimes you want a function that accepts any number of arguments. Use *args to collect extra positional arguments into a tuple:
def add_all(*numbers): """Add any number of values together.""" print(f"Received: {numbers}") return sum(numbers) print(add_all(1, 2)) print(add_all(1, 2, 3, 4, 5)) print(add_all(10))
Received: (1, 2)
3
Received: (1, 2, 3, 4, 5)
15
Received: (10,)
10
*args: A parameter prefixed with
* that collects all extra positional arguments into a tuple. The name args is a convention; you could use any name like *numbers.
def print_scores(student, *scores): """Print a student's name and all their scores.""" print(f"{student}'s scores:") for score in scores: print(f" - {score}") print_scores("Alice", 95, 87, 92) print_scores("Bob", 78)
Alice's scores:
- 95
- 87
- 92
Bob's scores:
- 78
5. **kwargs: Variable Keyword Arguments
Similarly, **kwargs collects extra keyword arguments into a dictionary:
def build_profile(name, **details): """Build a user profile from keyword arguments.""" profile = {"name": name} profile.update(details) return profile result = build_profile( "Alice", age=25, city="LA", major="CS" ) print(result)
{'name': 'Alice', 'age': 25, 'city': 'LA', 'major': 'CS'}
**kwargs: A parameter prefixed with
** that collects all extra keyword arguments into a dictionary. The name kwargs is a convention.
6. Putting It All Together
When combining different parameter types, they must appear in this order:
- Regular positional parameters
- Parameters with default values
*args**kwargs
def example(required, optional="default", *args, **kwargs): print(f"required: {required}") print(f"optional: {optional}") print(f"args: {args}") print(f"kwargs: {kwargs}") example("A", "B", "C", "D", x=1, y=2)
required: A
optional: B
args: ('C', 'D')
kwargs: {'x': 1, 'y': 2}
Real-World Example: Flexible Print Function
def log_message(message, level="INFO", **metadata): """Log a message with optional metadata.""" print(f"[{level}] {message}") for key, value in metadata.items(): print(f" {key}: {value}") log_message("Server started") log_message("Login failed", level="ERROR", user="alice", ip="192.168.1.1")
[INFO] Server started
[ERROR] Login failed
user: alice
ip: 192.168.1.1
Check Your Understanding
Question: What does this code print?
def repeat(text, times=2): return text * times print(repeat("ha")) print(repeat("ho", times=3))
Answer:
haha — uses the default times=2
hohoho — overrides with times=3
Try It Yourself
- Write a function
make_sandwich(bread, *fillings)that prints the bread type and all fillings - Write a function
calculate_price(amount, tax_rate=0.10, discount=0)that returns the final price - Call
calculate_priceusing keyword arguments to apply a 20% discount but keep the default tax rate
Key Takeaways
- Default values make parameters optional:
def func(x, y=10) - Keyword arguments use
name=valuesyntax for clarity and flexibility - Parameters with defaults must come after those without
*argscollects extra positional arguments into a tuple**kwargscollects extra keyword arguments into a dictionary- Order matters: regular, defaults, *args, **kwargs