Arguments & Parameters
Learn how to send information into functions using positional and keyword arguments, set smart default values, and dodge a sneaky beginner trap.
Functions are more useful when you can pass information into them. Instead of a function that always does the exact same thing, you can write one that adapts based on what you give it. That's what arguments and parameters are for.
Think of a function like a coffee machine. The machine is the function. The coffee beans, water amount, and cup size are the arguments — you choose them each time you press the button.
See it in action
— step through the idea, then dive into the details below.Functions That Adapt
A function that always does the same thing is useful. A function you can customize each time you call it is powerful. That's what arguments are for.
#Parameters vs Arguments
These two words sound similar, and beginners often mix them up. Here's the simple rule:
- A parameter is the variable name listed inside
defwhen you define the function. - An argument is the actual value you pass in when you call the function.
The parameter is the label on the slot. The argument is the thing you drop into it.
def greet(name): # 'name' is the PARAMETER
print("Hello,", name)
greet("Alice") # 'Alice' is the ARGUMENT
greet("Bob")#Positional Arguments
When you call a function with multiple arguments and just list them in order, those are positional arguments. Python matches them to parameters by their position — first argument goes to the first parameter, second to the second, and so on.
def describe_pet(animal, name):
print(name, "is a", animal)
describe_pet("dog", "Rex")
describe_pet("cat", "Whiskers")Order matters!
Swap the arguments and you swap the meaning. describe_pet("Rex", "dog") would print dog is a Rex — which makes no sense. Always double-check the order when using positional arguments.
#Keyword Arguments
You can also pass arguments by name, using the syntax parameter_name=value. These are called keyword arguments. When you use them, the order no longer matters — Python knows exactly which slot each value belongs to.
def describe_pet(animal, name):
print(name, "is a", animal)
# Using keyword arguments — order is flexible
describe_pet(name="Luna", animal="rabbit")Keyword arguments improve readability
When a function has several parameters, keyword arguments act like labels. A reader seeing send_email(to="alice@example.com", subject="Hi") immediately understands the code without looking up the function definition.
#Default Parameter Values
Sometimes a parameter almost always gets the same value. You can set a default value in the function definition using =. If the caller doesn't provide that argument, the default kicks in automatically.
def greet(name, greeting="Hello"):
print(greeting + ",", name + "!")
greet("Alice") # uses default greeting
greet("Bob", greeting="Hey") # overrides the default#Argument Order Rules
There is one strict rule you must follow: positional arguments must come before keyword arguments in a function call. Python will raise a SyntaxError if you break this rule.
def order_pizza(size, topping, extra_cheese=False):
print(size, topping, "cheese:", extra_cheese)
# Correct: positional first, then keyword
order_pizza("large", "pepperoni", extra_cheese=True)
# Also correct: all keyword
order_pizza(size="small", topping="mushroom")# This will cause a SyntaxError!
order_pizza(size="large", "pepperoni")#The Mutable Default Argument Gotcha
Here is one of the sneakiest traps in Python. It catches experienced programmers too. Never use a mutable object like a list or dictionary as a default parameter value.
Why? Because Python creates the default value once when the function is defined, not each time it is called. All calls that use the default end up sharing the exact same list object.
# DANGEROUS — don't do this!
def add_item(item, cart=[]):
cart.append(item)
return cart
print(add_item("apple"))
print(add_item("banana")) # the list is NOT empty!Mutable defaults are shared across all calls
The list [] in def add_item(item, cart=[]) is created a single time and reused every time cart is not provided. Changes to it stick around between calls. This is almost never what you want.
The fix is simple and idiomatic: use None as the default, then create a fresh list inside the function body if no value was passed.
# SAFE — the None pattern
def add_item(item, cart=None):
if cart is None:
cart = [] # fresh list every time
cart.append(item)
return cart
print(add_item("apple"))
print(add_item("banana")) # starts fresh, as expectedThink of it like a shared notepad
Using def f(items=[]) is like giving every customer in a coffee shop the same notepad to write their order. The second customer sees the first customer's order still there. Using None and creating a fresh list is like handing each customer a brand-new blank notepad.
What will this code print? ```python def power(base, exponent=2): return base ** exponent print(power(3)) print(power(3, exponent=3)) ```
Key takeaways
- Parameters are the variable names in `def`; arguments are the values you pass when calling.
- Positional arguments are matched by order; keyword arguments are matched by name.
- Default parameter values make arguments optional — great for common cases.
- Positional arguments must always come before keyword arguments in a call.
- Never use a mutable object (list, dict) as a default — use `None` and create it inside the function.
What does this code print?
def greet(name, greeting="Hello"):
print(greeting + ",", name + "!")
greet("Alice")
greet("Bob", greeting="Hi")This code has a bug. What is wrong?
def describe_pet(animal, name):
print(name, "is a", animal)
describe_pet(name="Rex", "dog")Complete the function definition so that calling make_tag("Hello") returns "<p>Hello</p>" and calling make_tag("Hi", tag="h1") returns "<h1>Hi</h1>".
def make_tag(content, tag=): return f"<{tag}>{content}</{tag}>"
Put these lines in the right order to define and call a safe add_item function that starts with a fresh list every time.
cart.append(item)
if cart is None:
cart = []
def add_item(item, cart=None):
return cart
Write a function called make_tag that takes a content string and an optional tag parameter that defaults to "p". It should return an HTML-style string wrapping the content in the tag, like <p>Hello</p>. Call it at least three times: once with just content, once overriding the tag positionally, and once overriding the tag as a keyword argument.
Try it live — edit the code and hit Run to execute real Python: