8.1.4. Core Operations#

import sys
from pathlib import Path

# Find project root by looking for _config.yml
current = Path.cwd()
for parent in [current, *current.parents]:
    if (parent / '_config.yml').exists():
        project_root = parent
        break
else:
    project_root = Path.cwd().parent.parent

# Add project root to path
sys.path.insert(0, str(project_root))

# Import shared teaching helpers and cell magics
from shared import thinkpython, diagram, jupyturtle, structshape
from shared.download import download

Common dictionary operations involve the following methods.

Group

Method

Description

Reading

d.get(key, default)

Get value safely, no KeyError

d.keys()

All keys

d.values()

All values

d.items()

All key-value pairs

Adding/Updating

d.update({...})

Add or overwrite from another dict

d.setdefault(key, default)

Set value only if key doesn’t exist

Removing

d.pop(key, default)

Remove & return a specific key

d.popitem()

Remove & return last inserted pair

d.clear()

Remove everything

Copying/Creating

d.copy()

Shallow copy

dict.fromkeys(keys, value)

Create new dict from a list of keys

Checking

'key' in d

Check if key exists

len(d)

Count of key-value pairs

8.1.4.1. Accessing Items#

Common ways to access values in a dictionary include:

  • dict[key]

  • dict.get(key)

  • dict.get(key, default)

We use square brackets [] to access and modify items in a Python dictionary by key. Reading a value looks like dict[key], which returns the value stored under key.

If a key you a key you try to access is missing, you will receive an error. To avoid the error, use dict.get(key), which returns None or a default value you provide when error.

person = {
    "name": "Alice",
    "age": 28,
    "city": "Rolla"
}

# Access an item
print(person["name"])      # Alice
print(person)
Alice
{'name': 'Alice', 'age': 28, 'city': 'Rolla'}

KeyError when trying to access a nonexistent key.

%%expect KeyError
print(person["phone"])      # KeyError
KeyError: 'phone'

When accessing, it is safer to use dict.get() to avoid the error because it

  • returns None when the key does not exist

  • returns a default value you specify when the key does not exist

print(person.get("phone"))          # None
print(person.get("phone", "N/A"))   # N/A
None
N/A
numbers = {'zero': 0, 'one': 1, 'two': 2}

To access all the keys and values at once:

  • keys() returns a view of all the dictionary’s keys

  • values() returns a view of all the dictionary’s values.

  • items() returns a view of all key-value pairs as tuples.

for k in numbers.keys():
    print(k, end=' ')
print()

for v in numbers.values():
    print(v, end=' ')
print()

for k, v in numbers.items():
    print(k, v , end=' ')
zero one two 
0 1 2 
zero 0 one 1 two 2 

The len function works on dictionaries; it returns the number of items.

len(numbers)
3
### Exercise: Accessing Dictionary Values
# Given the dictionary below:
person = {"name": "Bob", "age": 25, "city": "Chicago"}

# 1. Print the value associated with "name".
# 2. Use .get() to retrieve "email" with a default of "N/A".
# 3. Print all keys and values using .items().
### Your code starts here.



### Your code ends here.

Hide code cell source

person = {"name": "Bob", "age": 25, "city": "Chicago"}

# 1. Access "name"
print(person["name"])

# 2. Get "email" safely with a default
print(person.get("email", "N/A"))

# 3. Iterate with .items()
for key, value in person.items():
    print(key, value)
Bob
N/A
name Bob
age 25
city Chicago

8.1.4.2. Adding/Updating Items#

You also use the square brackets to update values. An item assignment like person["age"] = 30 will either

  • updates an existing item, or

  • creates a new item if the key does not already exist.

Note that, since dictionary keys are immutable, you can not modify it directly.

# Modify an existing item
person["age"] = 29

# Add a new item
person["email"] = "alice@rolla.com"

print(person)
{'name': 'Bob', 'age': 29, 'city': 'Chicago', 'email': 'alice@rolla.com'}

d.update() is used to add new key-value pairs or change existing ones in a dictionary. d.update() behaves like above but can work with multiple key-value pairs:

  • if the key already exists, its value is replaced

  • if the key does not exist, it is added

d = {"a": 1, "b": 2}
d.update({"b": 20, "c": 3})

print(d)   # {'a': 1, 'b': 20, 'c': 3}
{'a': 1, 'b': 20, 'c': 3}

An alternative syntax for d.update() is as follows.

d.update(a=10, d=4)
print(d)   # {'a': 10, 'b': 20, 'c': 3, 'd': 4}
{'a': 10, 'b': 20, 'c': 3, 'd': 4}

You cannot rename or update a key in place because dictionary keys are immutable. Instead, you could:

  1. Add a new key

  2. Copy the value

  3. Delete the old key

You can do all three steps in one line of code, because pop() will return the value that’s been removed, as shown below. I think that’s pretty neat.

student = {
    "name": "Doris",
    "age": 29
}

# Rename key "age" to "years"
student["years"] = student.pop("age")

print(student)
{'name': 'Doris', 'years': 29}
### Exercise: Adding and Updating Dictionary Items
# Start with this dictionary:
person = {"name": "Alice", "age": 28}

# 1. Add a new key "email" with value "alice@example.com".
# 2. Update "age" to 30.
# 3. Use d.update() to add "city": "Boston" and change "name" to "Alicia".
# 4. Print the final dictionary.
### Your code starts here.



### Your code ends here.

Hide code cell source

person = {"name": "Alice", "age": 28}

# 1. Add "email"
person["email"] = "alice@example.com"

# 2. Update "age"
person["age"] = 30

# 3. Use update()
person.update({"city": "Boston", "name": "Alicia"})

# 4. Print
print(person)
{'name': 'Alicia', 'age': 30, 'email': 'alice@example.com', 'city': 'Boston'}

8.1.4.3. Deleting Items#

You can delete items from a dictionary when you no longer need a key-value pair.

  • del: The del statement removes an item by its key, such as del person[“city”].

  • d.pop(): Another option is pop(), which removes the item and also returns its value, which is useful if you want to use that value later.

  • d.popitem(): removes and returns the last inserted key–value pair from a dictionary.

  • d.clear(): removes everything in the dictionary.

person = {
    "name": "Alice",
    "age": 29,
    "city": "Rolla",
    "email": "alice@rolla.com"
}
print("person:\t\t", person)

# Delete an item using del
del person["city"]                          # in place
print("city deleted:\t", person)

# Delete an item using pop()
email_popped = person.pop("email")

print("x_city_email:\t", person)            # {'name': 'Alice', 'age': 29}
print("email_popped:\t", email_popped)      # alice@rolla.com

print("person_updated\t", person)

# Delete the last added item using popitem() 
key, value = person.popitem()
print("popped_k_v:\t", (key, value))        # ('age', 29) or ('name', 'Alice') depending on the order of items in the dict
print("after_popitem:\t", person)           # {'name': 'Alice'}

# Clear all items from the dictionary
person.clear()
print("after_clear:\t", person)  # {}
person:		 {'name': 'Alice', 'age': 29, 'city': 'Rolla', 'email': 'alice@rolla.com'}
city deleted:	 {'name': 'Alice', 'age': 29, 'email': 'alice@rolla.com'}
x_city_email:	 {'name': 'Alice', 'age': 29}
email_popped:	 alice@rolla.com
person_updated	 {'name': 'Alice', 'age': 29}
popped_k_v:	 ('age', 29)
after_popitem:	 {'name': 'Alice'}
after_clear:	 {}
### Exercise: Deleting Dictionary Items
# Start with this dictionary:
person = {"name": "Bob", "age": 25, "city": "Boston", "email": "bob@email.com"}

# 1. Delete "city" using del.
# 2. Remove and capture "email" using pop(). Print the popped value.
# 3. Print the remaining dictionary.
### Your code starts here.



### Your code ends here.

Hide code cell source

person = {"name": "Bob", "age": 25, "city": "Boston", "email": "bob@email.com"}

# 1. Delete "city"
del person["city"]

# 2. Pop "email"
email_val = person.pop("email")
print("Popped email:", email_val)

# 3. Print remaining
print(person)
Popped email: bob@email.com
{'name': 'Bob', 'age': 25}

8.1.4.4. Membership Testing#

The in membership operator works on dictionaries, too; it tells you whether a key exists in the dictionary, which returns True if the key is present and False if it is not. You can also use not in to check that a key is missing.

Member testing is useful when you want to safely decide whether to access, update, or delete a dictionary item.

person = {
    "name": "Alice",
    "age": 29,
    "city": "Rolla"
}

print("name" in person)        # True
print("email" in person)       # False
print("email" not in person)   # True

if "age" in person:             # safety: Check if key exists before accessing
    print("Age exists:", person["age"])
True
False
True
Age exists: 29

The in operator does not check whether something appears as a value.

"Alice" in person
False

To see whether something appears as a value in a dictionary, you can use the method values, which returns a sequence of values, and then use the in operator.

"Alice" in person.values()
True
### Exercise: Membership Testing
# Use the dictionary below:
person = {"name": "Alice", "age": 29, "city": "Rolla"}

# 1. Check if "name" is in the dictionary and print the result.
# 2. Check if "phone" is NOT in the dictionary and print the result.
# 3. Check if "Alice" appears as a value and print the result.
### Your code starts here.



### Your code ends here.

Hide code cell source

person = {"name": "Alice", "age": 29, "city": "Rolla"}

# 1. "name" in person
print("name" in person)              # True

# 2. "phone" not in person
print("phone" not in person)         # True

# 3. "Alice" in values
print("Alice" in person.values())    # True
True
True
True