Skip to Content
Course content

66: Positional and Keyword Arguments

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I was looking through some old code for a shipping module I wrote a while back, and I stumbled across a function that perfectly illustrates how easy it is to shoot yourself in the foot if you aren't thinking about how Python handles arguments. Let's recreate the scenario.

The danger of relying on order

I have this function that processes an order. It takes the item name, the quantity, and the shipping priority. It's a simple setup:

def process_order(item, quantity, priority):
    print(f"Ordering {quantity}x {item} with {priority} shipping.")

# This works exactly as expected
process_order("Mechanical Keyboard", 2, "Express")
# Output: Ordering 2x Mechanical Keyboard with Express shipping.

Everything looks fine. But here is where things get messy. In a real project, these functions are often called from different files. Imagine I (or a teammate) forgot the exact order of the arguments and wrote this:

# I thought it was (quantity, item, priority)...
process_order(1, "Mechanical Keyboard", "Express")
# Output: Ordering Mechanical Keyboardx 1 with Express shipping.

Python didn't throw an error. Why? Because it just saw three values and mapped them to the three parameters in the order they appeared. It treated 1 as the item name and "Mechanical Keyboard" as the quantity. This is what we call positional arguments. They are convenient, but they are brittle.

Being explicit with keywords

I don't want to have to memorize the exact sequence of every function call in my codebase. To fix this, I can use keyword arguments. Instead of relying on the position, I'll explicitly tell Python which value belongs to which parameter.

# Now the order doesn't actually matter
process_order(priority="Express", item="Mechanical Keyboard", quantity=1)
# Output: Ordering 1x Mechanical Keyboard with Express shipping.

See that? Even though I put the priority first, Python knows exactly where everything goes. This makes the code much more readable—anyone glancing at the function call knows exactly what 1 and "Express" represent without having to jump back to the function definition.

Mixing the two approaches

Now, you might wonder if you have to name everything. You don't. You can mix them. I usually do this when the first few arguments are obvious, but the later ones might be confusing.

# Item and quantity are clear, but I'll be explicit about priority
process_order("Gaming Mouse", 5, priority="Overnight")

But there is a strict rule here that often trips people up. I tried to put a keyword argument before a positional one just to see what would happen:

# This will crash
process_order(item="Gaming Mouse", 5, "Overnight")
# SyntaxError: positional argument follows keyword argument

Python gets confused if you start naming things and then suddenly go back to just providing values. The rule is simple: positional arguments must always come first. Once you use a keyword argument, every argument following it in that call must also be a keyword argument.

Handling the "usually the same" values

In most of my orders, the shipping priority is just "Standard". It's tedious to type that every single time. I can set a default value in the function signature to handle this.

def process_order(item, quantity, priority="Standard"):
    print(f"Ordering {quantity}x {item} with {priority} shipping.")

# I can omit the priority entirely now
process_order("USB-C Cable", 10)
# Output: Ordering 10x USB-C Cable with Standard shipping.

# But I can still override it if I need to
process_order("USB-C Cable", 10, priority="Next Day Air")
# Output: Ordering 10x USB-C Cable with Next Day Air shipping.

By combining default values with keyword arguments, you create a function that is flexible. It's easy to use for the common case, but fully customizable when the situation demands it.




📋 Practical Task

Exercise: Fixing the Broken Inventory Order System

You've inherited a piece of code for a warehouse system. The original developer wrote a function to update stock, but it's causing bugs because the values are being passed in the wrong order. Your task is to fix the function calls using keyword arguments to ensure the data is mapped correctly, and add a default value to the function to make it more efficient.

Requirements:

  • Modify the update_stock function so that the category parameter defaults to "General".
  • Fix the two broken function calls below so that the product_name, amount, and category are assigned correctly, regardless of the order they are written in.
def update_stock(product_name, amount, category):
    print(f"Updating {product_name} ({category}): {amount} units added.")

# BUG: This is currently printing "Updating 50 (General): Desk Lamp units added."
update_stock(50, "Desk Lamp", "Lighting")

# BUG: This is currently printing "Updating Office Chair (Furniture): 12 units added." 
# (Wait, this one actually works positionally, but change it to use keyword arguments 
# to ensure it's safe from future changes!)
update_stock("Office Chair", 12, "Furniture")

# TEST: Call the function with only product_name and amount to test your default category.
update_stock("Paperclips", 100)
Rating
0 0

There are no comments for now.

to be the first to leave a comment.