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
60: The match Statement for Pattern Matching
Is this just a "switch" statement from other languages?
That's the first thing everyone asks, and the answer is: not exactly. If you're coming from C++ or Java, you're probably thinking of a simple value check. While match can do that, it's actually called "Structural Pattern Matching." The "structural" part is key. It doesn't just check if x == y; it checks if the shape of the data matches a specific pattern.
I usually use it when I'm dealing with commands or messages. Instead of a giant chain of if isinstance(...) and elif value == ..., you can describe what the data should look like. Check this out:
def handle_command(command):
match command.split():
case ["quit"]:
print("Shutting down...")
case ["load", filename]:
print(f"Loading file: {filename}")
case ["move", direction]:
print(f"Moving the character {direction}")
case _:
print("I don't understand that command.")
Notice how in the ["load", filename] case, Python isn't just checking if the list has two elements; it's actually extracting the second element and assigning it to the variable filename for you. That's a huge time-saver.
How do I handle more complex patterns, like dictionaries or objects?
This is where match really starts to outshine the old if/elif approach. You can match against the structure of a dictionary or even a custom class. You don't have to manually check for keys; you just define the keys you care about.
Imagine you're processing a JSON response from an API. You might only care about certain fields depending on the "type" of the response:
def process_event(event):
match event:
case {"type": "click", "x": x, "y": y}:
print(f"Mouse clicked at {x}, {y}")
case {"type": "keypress", "key": key}:
print(f"Key pressed: {key}")
case {"type": "scroll", "direction": dir}:
print(f"Scrolled {dir}")
case _:
print("Unknown event type")
I love this because it's declarative. You're telling Python, "If the dictionary has a key 'type' with the value 'click', and it also has 'x' and 'y', then do this." If the dictionary has extra keys you didn't mention, Python doesn't care—it still matches. It only cares that the requirements you specified are met.
Can I add extra logic to a case without writing a whole new block?
Yes, and this is a feature called "guards." Sometimes a pattern match isn't enough. You might know the shape of the data is correct, but you need to verify a specific value before proceeding. You do this by adding an if statement directly to the case line.
Here is a practical example. Let's say you're building a simple permission system. You want to match a user's role, but you only want to allow a "manager" to delete a record if the record is marked as "archived":
def delete_record(user, record):
match (user["role"], record["status"]):
case ("admin", _):
print("Admin delete: Allowed")
case ("manager", "archived"):
print("Manager delete: Allowed (Archived record)")
case ("manager", status) if status != "archived":
print(f"Manager delete: Denied. Record is {status}")
case _:
print("Delete: Denied")
That if status != "archived" is the guard. If the pattern matches (it's a manager and there is a status), but the guard evaluates to False, Python just skips that case and moves to the next one. It keeps your logic flat and readable instead of nesting if statements inside your case blocks.
What is the deal with the underscore symbol?
You've probably noticed the case _: at the end of my examples. In pattern matching, the underscore is the "wildcard." It matches anything. Since match evaluates cases from top to bottom, the wildcard acts as your else or default case.
One thing to keep in mind: if you use a variable name instead of an underscore (like case other:), Python actually binds the value to that variable. Using _ tells Python, "I know something is here, but I don't actually care what it is, so don't bother saving it to a variable." It's a small distinction, but it's cleaner and signals your intent to other developers.
📋 Practical Task
Building a Smart API Response Parser
You are building a system that processes responses from a weather API. The API returns a list containing a status code and a data payload. Depending on the status and the content of the payload, your program needs to respond differently.
Your Task: Write a function parse_weather_response(response) using a match statement that handles the following scenarios:
- If the response is
[200, {"temp": temperature, "unit": "C"}], print"The temperature is {temperature} degrees Celsius." - If the response is
[200, {"temp": temperature, "unit": "F"}], print"The temperature is {temperature} degrees Fahrenheit." - If the response is
[404, "City not found"], print"Error: The requested city was not found." - If the response is
[500, _](any data), print"Error: Server-side issue occurred." - For any other response shape, print
"Error: Received an unexpected response format."
Test your function with these inputs:
print(parse_weather_response([200, {"temp": 22, "unit": "C"}]))
print(parse_weather_response([200, {"temp": 72, "unit": "F"}]))
print(parse_weather_response([404, "City not found"]))
print(parse_weather_response([500, "Database connection timeout"]))
print(parse_weather_response([403, "Forbidden"]))There are no comments for now.