Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
66: Positional and Keyword Arguments
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_stockfunction so that thecategoryparameter defaults to"General". - Fix the two broken function calls below so that the
product_name,amount, andcategoryare 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)There are no comments for now.