Dictionary Dispatching
When we have a long list of if/elif or match-case blocks that simply return different values based on a single key, we can use a dictionary as a lookup table (or dispatch table). This maps keys directly to values or functions, making our code cleaner and easier to maintain.
Match-case Vs. Dictionary Lookup
Compare these two approaches for handling discount codes. Using .get() provides a safe default if the key is missing.
The Verbose Way (match-case)
user = {"coupon": "SAVE50"}
match user["coupon"]:
case "SAVE20":
discount = 0.20
case "SAVE50":
discount = 0.50
case _:
discount = 0.0
print(f"Discount: {discount}")
Output:
Discount: 0.5
The Pythonic Way (Dictionary Dispatch)
user = {"coupon": "SAVE50"}
# Create a mapping once
coupon_map = {"SAVE20": 0.20, "SAVE50": 0.50}
# Perform the lookup in one line with a default of 0.0
discount = coupon_map.get(user["coupon"], 0.0)
print(f"Discount: {discount}")
Output:
Discount: 0.5
Practical Example: Bulk Processing
Dictionary dispatching is extremely powerful when used inside loops to apply rules to a collection of data. Adding a new rule only requires adding one entry to the dictionary.
rules = {"gold": 0.20, "silver": 0.10, "bronze": 0.05}
customers = [
{"name": "Alice", "tier": "gold", "total": 100},
{"name": "Bob", "tier": "bronze", "total": 100}
]
for customer in customers:
# Look up the discount rate based on tier
rate = rules.get(customer["tier"], 0.0)
final_price = customer["total"] * (1 - rate)
print(f"{customer['name']} pays: ${final_price:.2f}")
Output:
Alice pays: $80.00
Bob pays: $95.00
Why It Scales Better
If we need to add more rules, we just update the rules dictionary. The actual logic inside the for loop doesn't have to change at all, separating our data from our logic.