Python Default Parameters
Table of Contents
In the last lesson, we learned about Python Return Values. Now let’s give a parameter a sensible value to use when the caller leaves it out.
🧩 Let’s Talk About Choices
Imagine we go to a coffee shop. We order a coffee. The barista asks, “Do you want sugar?” We say, “Yes, two sugars.” But most people just say, “Regular coffee.” The shop has a default: one sugar. If we don’t specify, we get one sugar.
That is exactly what default parameters are in Python. We can give a function a default value for a parameter. If the caller does not provide a value, the default is used. If they do provide a value, that value is used instead.
This makes our functions more flexible. We don’t have to pass every single argument every time. We only pass what we want to change.
🔧 How to Define a Default Parameter in Python
We define a default parameter by writing parameter=value in the function definition.
def greet(name, greeting="Hello"): print(f"{greeting}, {name}!")Here, greeting has a default value of "Hello". If we call greet("Alex"), it uses the default greeting.
greet("Alex")Output
Hello, Alex!But if we call greet("Alex", "Hi"), it uses "Hi" instead.
greet("Alex", "Hi")Output
Hi, Alex!We can also use keyword arguments to specify the greeting.
greet("Alex", greeting="Hey")Output
Hey, Alex!So the default is used only when we don’t provide a value.
⚙️ Multiple Default Parameters in Python
We can have multiple parameters with defaults. And we can mix them with parameters that don’t have defaults.
But there is a rule: parameters with defaults must come after parameters without defaults.
This is correct:
def order(item, quantity=1, size="medium"): print(f"{quantity} {size} {item}(s)")Here, item has no default. quantity and size have defaults.
We can call it in many ways:
order("coffee") # 1 medium coffee(s)order("tea", 2) # 2 medium tea(s)order("juice", 3, "large") # 3 large juice(s)order("water", size="small") # 1 small water(s)Output
1 medium coffee(s)2 medium tea(s)3 large juice(s)1 small water(s)Notice that if we skip quantity but want to specify size, we have to use the keyword size="small". Because positional arguments are matched left to right. So if we just write order("water", "small"), Python will think "small" is the quantity. That would be wrong. So we use keyword arguments to skip.
This is correct:
def order(item, quantity=1, size="medium"): print(f"{quantity} {size} {item}(s)")
order("water", size="small")Output
1 small water(s)But this is wrong:
order("water", "small") # This sets quantity="small", which is wrongOutput
small medium water(s)See? It doesn’t error, but it’s not what we intended. So let’s be careful with order.
📌 The Rule About Ordering in Python
As I said, parameters with defaults must come after parameters without defaults. This is not allowed:
def bad(a=1, b): # Error! print(a, b)Python will give us a syntax error: “non-default argument follows default argument.”
Why? Because if we allow that, it becomes ambiguous. When we call bad(5), is 5 for a or b? So Python forces us to put non-default parameters first.
This is correct:
def good(a, b=1): print(a, b)Now a is required, b is optional.
🧪 Python Default Parameters: A Real-Life Example
Let’s write a function that sends a message. We can specify the recipient, the message, and maybe a priority. The default priority is “normal”.
def send_message(recipient, message, priority="normal"): print(f"Sending to {recipient}: {message} [Priority: {priority}]")
send_message("Alex", "Hello!")send_message("Sam", "Meeting at 3", priority="high")Output
Sending to Alex: Hello! [Priority: normal]Sending to Sam: Meeting at 3 [Priority: high]That is very convenient. Most messages are normal priority. So we only specify priority when it’s different.
🏗️ Default Values Are Evaluated Once in Python
There is a subtle thing about default parameters. The default value is evaluated only once, when the function is defined. Not every time the function is called.
This matters when the default is a mutable object, like a list or a dictionary.
Let’s see an example.
def add_item(item, my_list=[]): my_list.append(item) return my_listNow if we call it:
print(add_item("apple"))print(add_item("banana"))print(add_item("cherry"))What do we expect? We might expect:
['apple']['banana']['cherry']But actually, we get:
['apple']['apple', 'banana']['apple', 'banana', 'cherry']Because the default list [] is created once. And it is shared across all calls. So each call appends to the same list.
This is a common gotcha. To avoid it, use None as the default and create a new list inside the function.
def add_item(item, my_list=None): if my_list is None: my_list = [] my_list.append(item) return my_listNow each call gets a fresh list.
print(add_item("apple")) # ['apple']print(add_item("banana")) # ['banana']print(add_item("cherry")) # ['cherry']That is the safe way. So let’s remember: avoid mutable default arguments unless we really know what we are doing.
⚠️ Common Mistakes with Python Default Parameters
❌ Mistake 1: Putting Default Before Non-Default
def bad(a=1, b): print(a, b)Error.
So what do we do? We put non-default parameters first.
def good(a, b=1): print(a, b)🚫 Mistake 2: Using Mutable Default
def add_item(item, my_list=[]): my_list.append(item) return my_listThis leads to unexpected behavior. So what do we do? We use None as default and create inside.
def add_item(item, my_list=None): if my_list is None: my_list = [] my_list.append(item) return my_list🛑 Mistake 3: Forgetting That Default Is Used Only When Argument Is Not Provided
If we pass None explicitly, it will use None, not the default.
def greet(name, greeting="Hello"): print(f"{greeting}, {name}!")
greet("Alex", None)Output
None, Alex!Because we passed None. The default is not used. So if we want to use the default, just omit the argument.
Next, we will learn about Python Keyword Arguments and pass values by parameter name.