Mental model: Think of unpacking as opening a gift box where each item is already labeled for you. Instead of digging through layers, Python hands you each part directly into the variables you named.
Unpacking pairs
orders = [(101, 'Laptop'), (204, 'Mouse')]
for order_id, product in orders:
print(f"Order {order_id}: got a {product}")
# Order 101: got a Laptop
# Order 204: got a MousePython matches the structure of each item to your variable names. This is cleaner than writing
for o in orders: oid = o[0]; prod = o[1]. It reads like a sentence, not an index lookup.Starred unpacking
temperatures = [22, 20, 24]
first_day, *later_days = temperatures
print(f"First: {first_day}°")
print(f"Rest: {later_days}")
# First: 22°
# Rest: [20, 24]* collects the remaining items into a list.You can place
*rest in other positions too. For example, first, *middle, last = [10, 20, 30] gives you the first and last elements separately, with everything else collected into a list.Unpacking dicts
def format_user(name, age, city):
return f"{name} is {age} from {city}"
profile = {'name': 'Ada', 'age': 36, 'city': 'London'}
print(format_user(**profile))
# Ada is 36 from London
** spreads dict keys as keyword arguments.The
** operator takes each key-value pair and passes it as a named argument. This keeps your function signatures clean while letting callers pass structured data without hardcoding every field name.Ignoring values
scores = [85, 92]
for _, score in enumerate(scores):
print(f"Score: {score}")
# Score: 85
# Score: 92
_ says out loud that the index is not needed here.When you don't need a value, name it
_. It signals intent: "I'm here because I have to be." This keeps your code readable and avoids lint warnings about unused variables. You're telling future readers exactly which parts of the data matter.