Python Dictionaries: Stop Counting Positions, Start Using Names
The data structure behind contact books, shopping carts, and almost every app you use, explained from zero.
Hey again! 👋
Let’s go back to that contact search from the loops post:
contacts = ["Alice", "Bob", "Charlie", "Diana", "Ethan"]It found names just fine. But be honest. What’s a contact book without phone numbers?
With what we know so far, you might try two lists side by side:
names = ["Alice", "Bob", "Charlie"]
phones = ["98450 11111", "98450 22222", "98450 33333"]This works… until it doesn’t. Sort one list and forget the other? Now Alice has Charlie’s number. Delete a name but not its phone? Everything shifts by one, and every contact after it is wrong. 😬
The problem is that we’re connecting data by position, and positions are fragile.
What we really want is to say: “Bob’s number is 98450 22222.” Connect things by name.
That’s exactly what a dictionary does.
What You’ll Master Today
By the end of this post, you’ll be able to:
✅ Create dictionaries and look up values by key
✅ Avoid the KeyError crash with .get()
✅ Add, update, and remove entries
✅ Loop through keys, values, and both at once
✅ Use the counting pattern (one of the most useful tricks in Python)
✅ Combine lists and dictionaries for real-world data
✅ Build a complete Contact Book app
Prerequisites: Everything so far, especially Lists and Functions.
Part 1: What Is a Dictionary?
Think of a real dictionary. You don’t find a word by saying “give me word number 4,812.” You look it up by the word itself, and you get its meaning.
Python dictionaries work the same way. Each entry is a key paired with a value:
contacts = {
"Alice": "98450 11111",
"Bob": "98450 22222",
"Charlie": "98450 33333",
}
print(contacts["Bob"])
# Output:
# 98450 22222Notice the differences from lists:
- Curly braces
{ }instead of square brackets - Each entry is
key: value - You look things up with the key, not a position number
Values can be anything: numbers, strings, booleans, even lists:
student = {
"name": "Priya",
"age": 21,
"course": "Computer Science",
"is_enrolled": True,
}
print(student["name"])
print(student["age"])
# Output:
# Priya
# 21That one variable now describes an entire student. That’s the power here: dictionaries let you group related information together, with labels.
Part 2: Looking Things Up Safely
What happens if you ask for a key that doesn’t exist?
print(student["email"])
# KeyError: 'email'Crash. 💥 This is the dictionary version of IndexError.
The safer way is .get():
print(student.get("email"))
print(student.get("email", "Not provided"))
# Output:
# None
# Not provided.get() returns None if the key is missing, or whatever default you give it. No crash.
Get Ajay Narayan’s stories in your inbox
Join Medium for free to get updates from this writer.
When to use which:
student["name"]when you're sure the key exists (and want a loud error if it doesn't)student.get("email")when the key might be missing
Two rules about keys
1. Keys must be unique. If you repeat one, the last value wins:
settings = {"theme": "light", "theme": "dark"}
print(settings)
# Output:
# {'theme': 'dark'}2. Keys must be unchangeable types, usually strings or numbers. You can’t use a list as a key (lists can change, remember?). Values, though, can be anything.
Part 3: Adding, Updating, and Removing
Dictionaries are mutable, just like lists.
Adding and updating use the same syntax
student = {"name": "Priya", "age": 21}
student["email"] = "priya@example.com" # new key: adds it
student["age"] = 22 # existing key: updates it
print(student)
# Output:
# {'name': 'Priya', 'age': 22, 'email': 'priya@example.com'}If the key exists, Python updates it. If it doesn’t, Python creates it. One line handles both.
Removing entries
student = {"name": "Priya", "age": 22, "email": "priya@example.com", "course": "CS"}
del student["email"] # remove a key
course = student.pop("course") # remove it AND get the value back
print(course)
print(student)
# Output:
# CS
# {'name': 'Priya', 'age': 22}Same idea as lists: del just deletes, .pop() deletes and hands you the value.
Checking if a key exists
print("name" in student)
print("Priya" in student)
# Output:
# True
# FalseCareful! in checks keys, not values. "Priya" is a value, so it returns False. This catches a lot of people.
Part 4: Looping Through Dictionaries
There are three ways, depending on what you need:
prices = {"apple": 30, "bread": 45, "milk": 28}
# Keys only (this is the default)
for item in prices:
print(item)
# Values only
for price in prices.values():
print(price)
# Both at once (the one you'll use most)
for item, price in prices.items():
print(f"{item} costs ₹{price}")
# Output:
# apple
# bread
# milk
# 30
# 45
# 28
# apple costs ₹30
# bread costs ₹45
# milk costs ₹28.items() gives you each key and value as a pair, and for item, price in ... unpacks them into two variables. It looks just like enumerate from the lists post, right? Same idea.
💡 Since Python 3.7, dictionaries remember the order you added things. So they print in the order you created them.
Part 5: The Counting Pattern
This is one of the most useful patterns in all of Python. Let’s count how many times each word appears in a sentence:
sentence = "the cat sat on the mat the end"
counts = {}
for word in sentence.split():
counts[word] = counts.get(word, 0) + 1
print(counts)
# Output:
# {'the': 3, 'cat': 1, 'sat': 1, 'on': 1, 'mat': 1, 'end': 1}Let’s unpack that key line:
sentence.split()breaks the string into a list of wordscounts.get(word, 0)means "what's the count so far? If we haven't seen this word, it's 0"+ 1adds this occurrencecounts[word] = ...saves the new count
Remember the counter pattern from the loops post? This is the same idea, except instead of one counter, you get a separate counter for every word, all created automatically.
The same pattern counts votes, letters, website visits, product sales, error types… once you see it, you’ll spot it everywhere.
Part 6: Lists + Dictionaries = Real Data
Here’s where it all comes together. Real-world data is usually a list of dictionaries: a list of students, a list of products, a list of orders.
students = [
{"name": "Priya", "marks": 88},
{"name": "Rahul", "marks": 74},
{"name": "Sneha", "marks": 93},
]
for s in students:
print(f"{s['name']}: {s['marks']}")
top = students[0]
for s in students:
if s["marks"] > top["marks"]:
top = s
print(f"Top student: {top['name']} ({top['marks']})")
# Output:
# Priya: 88
# Rahul: 74
# Sneha: 93
# Top student: Sneha (93)Small detail: inside the f-string we used s['name'] with single quotes, because the f-string itself uses double quotes. Mix them up and Python gets confused about where the string ends.
If you ever work with APIs or JSON data (and you will), it looks exactly like this. You’re already learning the shape of real-world data.
Real-World: Shopping Cart Bill
Two dictionaries working together, one for prices and one for what’s in the cart:
prices = {"apple": 30, "bread": 45, "milk": 28, "eggs": 7}
cart = {"apple": 4, "milk": 2, "eggs": 12}
print("Your Bill")
print("-" * 40)
total = 0
for item, qty in cart.items():
cost = prices[item] * qty
print(f"{item} x {qty} = ₹{cost}")
total += cost
print("-" * 40)
print(f"Total: ₹{total}")
# Output:
# Your Bill
# ----------------------------------------
# apple x 4 = ₹120
# milk x 2 = ₹56
# eggs x 12 = ₹84
# ----------------------------------------
# Total: ₹260Prices change? Update one dictionary. New product? Add one line. No positions to keep in sync. That’s the dictionary advantage.
Mini Project: Contact Book
Time to build the contact book we started with, properly this time, with phone numbers, search, and delete:
def show_contacts(contacts):
if not contacts:
print("\nYour contact book is empty.")
return
print("\nContacts:")
for name in sorted(contacts):
print(f" {name}: {contacts[name]}")
def add_contact(contacts):
name = input("Name: ").strip().title()
if name in contacts:
print(f"{name} already exists. Updating their number.")
phone = input("Phone: ").strip()
contacts[name] = phone
print(f"Saved {name}. ✅")
def search_contact(contacts):
name = input("Search name: ").strip().title()
phone = contacts.get(name)
if phone:
print(f"{name}: {phone}")
else:
print(f"No contact named '{name}'.")
def delete_contact(contacts):
name = input("Name to delete: ").strip().title()
if name in contacts:
del contacts[name]
print(f"Deleted {name}.")
else:
print(f"No contact named '{name}'.")
def main():
contacts = {}
print("=" * 50)
print("CONTACT BOOK")
print("=" * 50)
while True:
print("\n1. View all")
print("2. Add / update")
print("3. Search")
print("4. Delete")
print("5. Quit")
choice = input("Choose (1-5): ")
if choice == "1":
show_contacts(contacts)
elif choice == "2":
add_contact(contacts)
elif choice == "3":
search_contact(contacts)
elif choice == "4":
delete_contact(contacts)
elif choice == "5":
print(f"Goodbye! {len(contacts)} contact(s) saved.")
break
else:
print("Invalid choice. Try again.")
main()A couple of things to notice:
.strip().title()cleans up the input..strip()removes extra spaces, and.title()turns"alice"or"ALICE"into"Alice". That way searching works no matter how the user types the name.sorted(contacts)sorts the dictionary's keys, so contacts always show alphabetically.- Look at the structure. It’s the same menu loop as the calculator and the to-do app. Once you learn this pattern, you can build almost any small command-line app with it.
Compare this to the list version from the loops post. Searching used to need a loop and a found flag. Now it's one line: contacts.get(name). Dictionaries are fast to search, too. Even with a million contacts, lookup by key is nearly instant.
Practice Challenges
Beginner Level
- Capitals: Create a dictionary of 3 countries and their capitals. Loop through it with
.items()and print each pair. - Capital Lookup: Ask the user for a country and print its capital, or “Unknown” if it’s not in your dictionary (use
.get()).
Intermediate Level
- Letter Counter: Ask for a word and use the counting pattern to count each letter. For
"banana", you should get{'b': 1, 'a': 3, 'n': 2}. - Flip It: Write a function that takes a dictionary and returns a new one with the keys and values swapped.
Advanced Level
- Grade Book: Create a dictionary where each key is a student’s name and each value is a list of their marks, like
{"Priya": [88, 92, 79], ...}. Print each student's average, then print the class topper. (Lists inside dictionaries: this is how real apps store data!)
Before You Go
Did dictionaries click for you? Hit that 👏 clap button.
Built the contact book? Try adding an email address to each contact (hint: the value could be another dictionary 👀). Show me in the comments!
Coming up next: Tuples and Sets, the two collection types that round out your Python toolkit. Hit Follow so you don’t miss it.
See you in the next post! 🐍✨
Enjoying this series? Share it with a friend learning Python. Let’s all grow faster, together.
Check out the series so far:






