FunctionsBeginner7 min33 / 63

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

Visual walkthrough1 / 6
1

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.

Think of a function like a coffee machine — you choose the beans, water, and cup size each time you press the button.

#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 def when 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.

Same function, different arguments each call.
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.

Order matters with positional arguments.
def describe_pet(animal, name):
    print(name, "is a", animal)

describe_pet("dog", "Rex")
describe_pet("cat", "Whiskers")
Watch out

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.

Keyword arguments make code self-documenting.
def describe_pet(animal, name):
    print(name, "is a", animal)

# Using keyword arguments — order is flexible
describe_pet(name="Luna", animal="rabbit")
Tip

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.

Defaults make arguments optional for callers.
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.

Positional before keyword — always.
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")
Keyword before positional is not allowed.
# 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.

The default list persists across calls — a nasty surprise.
# 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!
Common mistake

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.

Use None as the default, then create the list inside the function.
# 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 expected
Think of it like

Think 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.

Quick check

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.
Practice challenges
Test yourself · earn XP
0/4
Predict the output#1

What does this code print?

predict-output
def greet(name, greeting="Hello"):
    print(greeting + ",", name + "!")

greet("Alice")
greet("Bob", greeting="Hi")
Fix the bug#2

This code has a bug. What is wrong?

fix-bug
def describe_pet(animal, name):
    print(name, "is a", animal)

describe_pet(name="Rex", "dog")
Fill in the blank#3

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}>"
Reorder the lines#4

Put these lines in the right order to define and call a safe add_item function that starts with a fresh list every time.

1
    cart.append(item)
2
    if cart is None:
3
        cart = []
4
def add_item(item, cart=None):
5
    return cart
Your turn
Practice exercise

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:

solution.py · editable