dict: Key and Value
- Create a dict and read a value by key
- Add, update and delete key-value pairs
- Use
getwith a default to avoid a KeyError - Loop over a dictionary with keys, values and items, and work with a list of dictionaries
What will we learn?
A dict (Dictionary) is a structure that holds pairs of a key and a value. Instead of accessing by position ([0]), you access by name (["name"]).
Why do we need this?
In the tuple ("Dana", 24, "Haifa") you have to remember that position 1 is the age. With 15 fields, that is a recipe for bugs. A dict solves this:
student = {"name": "Dana", "age": 24, "city": "Haifa"}
student["age"] # clear and readabledict is perhaps the most important structure for the coming weeks:
- JSON (tomorrow): the format in which files are saved and information is sent over the network. In Python it becomes a dict.
- The backend and databases topics: every request and response in an API is essentially a dict.
{"id": 7, "name": "Dana"}. - Every “record”, like a user, a product or an order, is convenient to represent as a dict.
Explanation from the basics
What is a dict?
- Every item is a pair: a Key → a Value.
- Unique keys — there are no two identical keys. Assigning to an existing key replaces the value.
- Mutable.
- Keeps the insertion order (since Python 3.7).
- A key is usually a
stror anint. A value can be anything: a number, text, a list, and even another dict.
In a real dictionary you look up a word (the key) and get a definition (the value). You don’t look for “the definition at position 5,000 in the book”. In a phone book: name → number. Two people cannot appear with exactly the same name as separate entries. A new entry with the same name replaces the previous one.
Syntax
# create
empty = {}
student = {"name": "Dana", "age": 24}
# read
student["name"] # "Dana" - KeyError if the key does not exist
student.get("email") # None - no error if missing
student.get("email", "N/A") # "N/A" - default value if missing
# add / update (same syntax!)
student["email"] = "dana@mail.com" # new key -> added
student["age"] = 25 # existing key -> updated
# delete
del student["email"] # delete a key (KeyError if missing)
age = student.pop("age") # delete and return the value
# check
"name" in student # True - checks KEYS, not values
len(student) # number of key-value pairs
# iterate
for key in student: # keys
for value in student.values(): # values
for key, value in student.items(): # pairs (tuples!)First code example
week-2/student_dict.py:
student = {"name": "Dana", "age": 24, "city": "Haifa"}
print("Name:", student["name"])
print("Age:", student["age"])
student["age"] = 25
student["email"] = "dana@mail.com"
print("Updated:", student)
del student["city"]
print("After delete:", student)
print("Has email?", "email" in student)
print("Phone:", student.get("phone", "not provided"))Output:
Name: Dana
Age: 24
Updated: {'name': 'Dana', 'age': 25, 'city': 'Haifa', 'email': 'dana@mail.com'}
After delete: {'name': 'Dana', 'age': 25, 'email': 'dana@mail.com'}
Has email? True
Phone: not providedBreaking down the code line by line
| Line | Explanation |
|---|---|
{"name": "Dana", ...} | A key, a colon, a value. Pairs are separated by commas. |
student["name"] | Reading by key: the value "Dana". |
student["age"] = 25 | The key exists, so the value is updated. |
student["email"] = "..." | The key does not exist, so it is added (at the end). Exactly the same syntax! |
del student["city"] | Deleting the whole pair. |
"email" in student | Checks whether the key exists. |
student.get("phone", "not provided") | The key does not exist, so the default is returned, without an error. |
Another example
A list of dictionaries — the most common structure for “real” data (a table: every dict is a row). And also counting with a dict. week-2/products.py:
products = [
{"id": 1, "name": "Laptop", "price": 3500, "category": "electronics"},
{"id": 2, "name": "Mouse", "price": 80, "category": "electronics"},
{"id": 3, "name": "Desk", "price": 900, "category": "furniture"},
{"id": 4, "name": "Chair", "price": 450, "category": "furniture"},
]
print("--- Catalog ---")
for product in products:
print(product["id"], product["name"], product["price"], "NIS")
expensive = []
for product in products:
if product["price"] > 500:
expensive.append(product["name"])
print("Over 500 NIS:", expensive)
count_by_category = {}
for product in products:
category = product["category"]
count_by_category[category] = count_by_category.get(category, 0) + 1
print("Count by category:", count_by_category)
for category, count in count_by_category.items():
print(category, "->", count, "products")Output:
--- Catalog ---
1 Laptop 3500 NIS
2 Mouse 80 NIS
3 Desk 900 NIS
4 Chair 450 NIS
Over 500 NIS: ['Laptop', 'Desk']
Count by category: {'electronics': 2, 'furniture': 2}
electronics -> 2 products
furniture -> 2 productsBreakdown:
productsis a list where every item is a dict.product["price"]= the price of the current product in the loop.- The counting pattern:
count_by_category.get(category, 0) + 1. If the category is not in the dictionary yet,getreturns 0, and then 0+1 = 1. If it is already there, you get the existing count and add 1. This is a pattern that comes up again and again. .items()— returns(key, value)pairs as tuples, andfor category, count inunpacks them (Unpacking from the previous lesson).
A dict inside a dict
A value can be a dict itself:
user = {
"name": "Dana",
"address": {"city": "Haifa", "street": "Herzl 10"},
"hobbies": ["chess", "running"],
}
print(user["address"]["city"]) # Haifa
print(user["hobbies"][0]) # chessYou access it “layer by layer”: user["address"] returns a dict, and on it ["city"]. That is exactly the structure of JSON.
Common mistake
Mistake 1: a KeyError on a key that does not exist.
student = {"name": "Dana"}
print(student["age"])KeyError: 'age'The fix: student.get("age") (returns None), student.get("age", 0) (a default), or check first with if "age" in student:.
Mistake 2: searching for a value with in.
student = {"name": "Dana"}
print("Dana" in student)Falsein on a dict checks keys. To check values: "Dana" in student.values().
Mistake 3: a typo in a key, which creates a new key instead of updating.
student = {"name": "Dana", "age": 24}
student["Age"] = 25
print(student){'name': 'Dana', 'age': 24, 'Age': 25}No error! A new key "Age" was simply added, and "age" stayed 24. Keys are case-sensitive. It is a silent Logical Error, so keep the key names consistent (snake_case).
Mistake 4: a list as a key.
locations = {[32, 35]: "Haifa"}TypeError: unhashable type: 'list'A key must be Immutable. If you need a key made of several values, use a tuple: {(32, 35): "Haifa"}. (We will explain the connection to Immutable in the next lesson.)
Practice
The exercises use only what was taught in this lesson and the lessons before it. Try on your own first, and only then open the solution.
Exercise 1: A student card
Create a dictionary student with the name "Dana", the age 24 and the city "Haifa". Then:
- Update the age to 25.
- Add an email
"dana@mail.com". - Delete the city.
- Print the dictionary, and the phone using
getwith the default"none".
Expected output:
{'name': 'Dana', 'age': 25, 'email': 'dana@mail.com'}
noneShow solution
student = {"name": "Dana", "age": 24, "city": "Haifa"}
student["age"] = 25
student["email"] = "dana@mail.com"
del student["city"]
print(student)
print(student.get("phone", "none")){'name': 'Dana', 'age': 25, 'email': 'dana@mail.com'}
nonestudent["phone"] would throw a KeyError. get returns a default value when the key does not exist.
Exercise 2: Counting words
Write a function count_words(text) that returns a dictionary: every word (in lowercase) → how many times it appears.
counts = count_words("the cat and the dog and THE bird")
print(counts)Expected output:
{'the': 3, 'cat': 1, 'and': 2, 'dog': 1, 'bird': 1}Show solution
def count_words(text):
counts = {}
for word in text.lower().split():
counts[word] = counts.get(word, 0) + 1
return counts
counts = count_words("the cat and the dog and THE bird")
print(counts){'the': 3, 'cat': 1, 'and': 2, 'dog': 1, 'bird': 1}counts.get(word, 0) returns 0 for a word that was not counted yet — that way you do not need a separate if for a new word.
Exercise 3: A list of dictionaries
products = [
{"name": "Laptop", "price": 3500, "category": "electronics"},
{"name": "Mouse", "price": 80, "category": "electronics"},
{"name": "Desk", "price": 900, "category": "furniture"},
]- Print the names of the products whose price is below 1000.
- Build a dictionary that counts how many products there are in each category, and print it.
Expected output:
Mouse
Desk
{'electronics': 2, 'furniture': 1}Show solution
products = [
{"name": "Laptop", "price": 3500, "category": "electronics"},
{"name": "Mouse", "price": 80, "category": "electronics"},
{"name": "Desk", "price": 900, "category": "furniture"},
]
for product in products:
if product["price"] < 1000:
print(product["name"])
counts = {}
for product in products:
category = product["category"]
counts[category] = counts.get(category, 0) + 1
print(counts)Mouse
Desk
{'electronics': 2, 'furniture': 1}Exercise 4: Looping over a dictionary
stock = {"apple": 12, "banana": 0, "cherry": 5}Loop over the dictionary with items() and print every item and its quantity. For an item whose quantity is 0, print out of stock.
Expected output:
apple -> 12
banana -> out of stock
cherry -> 5Show solution
stock = {"apple": 12, "banana": 0, "cherry": 5}
for name, quantity in stock.items():
if quantity == 0:
print(name, "->", "out of stock")
else:
print(name, "->", quantity)apple -> 12
banana -> out of stock
cherry -> 5items() returns pairs of a key and a value, and Unpacking in the loop splits each pair into two variables.
Exercise 5: A nested dictionary
user = {
"name": "Dana",
"address": {"city": "Haifa", "street": "Herzl"},
"hobbies": ["chess", "running"],
}Print the city, the first hobby, and add a hobby "music". At the end, print the list of hobbies.
Expected output:
Haifa
chess
['chess', 'running', 'music']Show solution
user = {
"name": "Dana",
"address": {"city": "Haifa", "street": "Herzl"},
"hobbies": ["chess", "running"],
}
print(user["address"]["city"])
print(user["hobbies"][0])
user["hobbies"].append("music")
print(user["hobbies"])Haifa
chess
['chess', 'running', 'music']Every [ ] goes one level deeper: user["address"] is a dictionary, and ["city"] takes a value out of it. That is exactly the structure of JSON.
Summary
- dict
{key: value}— access by key and not by position. Keys are unique. d[key] = value— adds if new, updates if it exists.d[key]throws aKeyErroron a missing key.d.get(key, default)does not throw.inchecks keys. Looping:keys(),values(),items()(pairs).- A list of dictionaries = a table. A dict inside a dict = JSON.
- The counting pattern:
counts[x] = counts.get(x, 0) + 1.