Dictionary type
Contents
18. Dictionary type#
Author: Tue Nguyen
18.1. Outline#
What is a dictionary?
Create a dictionary
Elements of a dict
Iterate through a dictionary
Copy a dictionary
Operations on dictionaries
Dict comprehensions
18.2. What is a dictionary?#
A dictionary (or dict) is used to store data in the form of
key: value
pairsEach element of a dict is has a
key
part and avalue
partElements are accessed using
key
Dicts are mutable
The keys must be unique and of an immutable type
However, the values can be of any types
For Python
<= 3.6
, dicts are not orderedFor Python
>= 3.7
, dicts are insertion ordered
18.3. Create a dict#
18.3.1. Use {}
#
# A dict with one element
d = {"name": "John"}
print(d)
print(type(d))
{'name': 'John'}
<class 'dict'>
# For a dict with multi elements
# We can span more than 1 line for readability
d = {
"name": "John",
"age": 20,
"country": "UK"
}
print(d)
{'name': 'John', 'age': 20, 'country': 'UK'}
18.3.2. Use dict()
#
d = dict(
name="John",
age=20,
country="UK"
)
print(d)
{'name': 'John', 'age': 20, 'country': 'UK'}
18.4. Elements of a dict#
18.4.1. Keys, values, and items#
# Recall the dict
d
{'name': 'John', 'age': 20, 'country': 'UK'}
# Get keys
d.keys()
dict_keys(['name', 'age', 'country'])
# Get values
d.values()
dict_values(['John', 20, 'UK'])
# View elements as a sequence of tuples
# Keys are the first elements in the tuples
# We usually use this when iterate through a list
d.items()
dict_items([('name', 'John'), ('age', 20), ('country', 'UK')])
18.4.2. Get values by keys#
# Get value associated with name
d["name"]
'John'
# Get value associated with country
d["country"]
'UK'
18.4.3. Add and update elements#
We use assignment to add a new elements or update the value for an exisiting element
# Init
d = {"name": "John", "age": 20}
d
{'name': 'John', 'age': 20}
# Add education
d["educ"] = "BSc"
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
# Now update education to MSc
d["educ"] = "MSc"
d
{'name': 'John', 'age': 20, 'educ': 'MSc'}
18.5. Dict keys#
a) Dict keys must be of immutable types
# Int keys
{1: True, 2: "A"}
{1: True, 2: 'A'}
# Float keys are possible but not recommended
# Because computer store floats approximately
{1.2: True, 5.: "B"}
{1.2: True, 5.0: 'B'}
# String keys
{"name": "John", "age": 20}
{'name': 'John', 'age': 20}
# Tuple keys
d = {
("US", "gdp"): 19.49,
("US", "pop"): 325,
("CN", "gdp"): 12.24,
("CN", "pop"): 1421
}
print(d[("US", "gdp")]) # GDF of US
print(d[("CN", "pop")]) # Population of china
19.49
1421
b) Dict keys must be unique
# Try to duplicate a key, only the latter is kept
{"name": "John", "age": 20, "age": 30}
{'name': 'John', 'age': 30}
18.6. Conversion to dicts#
We use dict()
to convert an object to a dict
# Convert a sequence of 2-element squences
data = [("name", "John"), ("age", 20)]
dict(data)
{'name': 'John', 'age': 20}
# Convert a zipped object to a dict
names = ["A", "B"]
ages = [20, 30]
dict(zip(names, ages))
{'A': 20, 'B': 30}
18.7. Iterate through a dict#
# Init a dict
d = {"name": "John", "age": 20, "educ": "MSc"}
d
{'name': 'John', 'age': 20, 'educ': 'MSc'}
18.7.1. Iterate through keys#
# Method 1
for k in d:
print(k)
name
age
educ
# Method 2
for k in d.keys():
print(k)
name
age
educ
18.7.2. Iterate through values#
for v in d.values():
print(v)
John
20
MSc
18.7.3. Iterate through both keys and values#
# Naive way
for k in d:
print(f"Key {k} has value {d[k]}")
Key name has value John
Key age has value 20
Key educ has value MSc
# Better way
for k, v in d.items():
print(f"Key {k} has value {v}")
Key name has value John
Key age has value 20
Key educ has value MSc
What happened?
Recall that each element of
d.items()
is 2-element tupleThus writing
k, v
in the for loop means we unpack the corresponding tuple at each iterationThus the key goes to
k
and the value goes tov
18.8. Mutablity#
A dict is mutable
We can add, update, or delete elements
18.9. Copy a dict#
Since the dict
type is mutable, copying a dict has the same behavior as copying a list
18.9.1. Shallow copying#
# Init a dict
d = {"name": "John", "degrees": ["BSc", "MSc"]}
print(d)
print(id(d))
{'name': 'John', 'degrees': ['BSc', 'MSc']}
139923067098176
# Make a shallow copy
d2 = d.copy()
# Verify d and d2 have the same values
print(d)
print(d2)
print(d == d2)
{'name': 'John', 'degrees': ['BSc', 'MSc']}
{'name': 'John', 'degrees': ['BSc', 'MSc']}
True
# But d and d2 are pointing to different objects
print(id(d))
print(id(d2))
print(d is d2)
139923067098176
139923101568704
False
# Changing name of d (a string - immutable)
# will not change name of d2
d["name"] = "Jack"
print(d)
print(d2)
{'name': 'Jack', 'degrees': ['BSc', 'MSc']}
{'name': 'John', 'degrees': ['BSc', 'MSc']}
# But modifying degrees of d (a list - mutable)
# will also modify that of d2
d["degrees"][0] = "PhD"
print(d)
print(d2)
{'name': 'Jack', 'degrees': ['PhD', 'MSc']}
{'name': 'John', 'degrees': ['PhD', 'MSc']}
18.9.2. Deep copying#
Same as lists, we use copy.deepcopy()
# Init
d = {"name": "John", "degrees": ["BSc", "MSc"]}
d
{'name': 'John', 'degrees': ['BSc', 'MSc']}
# Import module copy
import copy
# Make a deep copy
d2 = copy.deepcopy(d)
# Change degrees of d, d2 stays the same
d["degrees"][0] = "PhD"
print(d)
print(d2)
{'name': 'John', 'degrees': ['PhD', 'MSc']}
{'name': 'John', 'degrees': ['BSc', 'MSc']}
18.10. Operations on a dict#
As a mutable type like lists, we also have two types of operations on dicts
Regular operations
Inplace operations
18.10.1. Regular operations#
# Init a dict
d = {"name": "John", "age": 20, "educ": "BSc"}
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
Get value by key
# Traditional way
d["name"]
'John'
# However, if the key is not in d, we will get an error
# Try d["weight"]
# To avoid an error, we can use .get
# If the key is not in d, we will get a None back
w = d.get("weight")
print(w)
None
# If we don't like None, we can set the default value
d.get("weight", "N/A")
'N/A'
Count number of elements
len(d)
3
Member ship checking
# Check if d has a key "age"
"age" in d
True
# Check if d has a key "address"
"address" in d
False
# Check if d has a value 20
20 in d.values()
True
18.10.2. Inplace operations#
# Init a dict
d = {"name": "John", "age": 20, "educ": "BSc"}
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
Add or update elements
# Add country
d["country"] = "UK"
d
{'name': 'John', 'age': 20, 'educ': 'BSc', 'country': 'UK'}
# Update country to "US"
d["country"] = "US"
d
{'name': 'John', 'age': 20, 'educ': 'BSc', 'country': 'US'}
Delete an element
# Use del to delete by key
del d["country"]
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
# However, if key is not in d, we will get an error
# Try del d["weight"] to see it
# We can use an if statement to avoid this
if "weight" in d:
del d["weight"]
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
Set default
Sometimes, we are not sure if a key already exists
If it exists, we want to leave it as it is
If not, we want to add a new element with the key and a default value
# Init a dict
d = {"name": "John", "age": 20, "educ": "BSc"}
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
# If key "age" exists, leave it as it is
# If not, add a new element with that key and value -1
d.setdefault("age", -1)
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
# If key "credits" exists, leave it as it is
# If not, add a new element with that key and value 0
d.setdefault("credits", 0)
d
{'name': 'John', 'age': 20, 'educ': 'BSc', 'credits': 0}
Pop an element
# We can pop a value by key
# Also note that if the key is not in d, we will get an error
educ = d.pop("educ")
print(educ)
print(d)
BSc
{'name': 'John', 'age': 20, 'credits': 0}
Update a dict
# Init 2 dict
d = {"name": "John", "age": 20}
d2 = {"age": 22, "educ": "BSc"}
print(d)
print(d2)
{'name': 'John', 'age': 20}
{'age': 22, 'educ': 'BSc'}
# Update d with info from d2
# Key "educ" is new to d -> new element is created for this key
# Key "age" already exists in d -> update the value for this key from d2
d.update(d2)
d
{'name': 'John', 'age': 22, 'educ': 'BSc'}
18.11. Dict comprehensions#
Dict comprehensions are similar to list comprehensions
Used to quickly make a dict from an iterable
Syntax 1 (without filtering):
{key_expr: value_expr for item in iterable}
Syntax 2 (with filtering):
{key_expr: value_expr for item in iterable if condition}
# Make a dict from a list of words
# Keys are words in lowercase
# Values are words in uppercase
words = ["Cat", "Dog", "Cow", "Duck"]
{w.lower(): w.upper() for w in words}
{'cat': 'CAT', 'dog': 'DOG', 'cow': 'COW', 'duck': 'DUCK'}
# From list words above, make a dict
# Keys are the position of the word
# Value are the words themselves
{(i+1): v for i, v in enumerate(words)}
{1: 'Cat', 2: 'Dog', 3: 'Cow', 4: 'Duck'}
# Make a dict
# Keys are integers from 1 to 5
# Values are squares of keys
{v:v**2 for v in range(1, 6)}
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# From list words above, make a list
# Keys are words
# Values are the numbers of characters
# Only keep words with <= 3 characters
{w: len(w) for w in words if len(w) <= 3}
{'Cat': 3, 'Dog': 3, 'Cow': 3}
18.12. Summary#
What is a dictionary?
Mutable object storing data in the form of
key: value
pairsEach element of a dict is has a
key
part and avalue
partElements are accessed using
key
The keys must be unique and of an immutable type
However, the values can be of any types
For Python
<= 3.6
, dicts are not orderedFor Python
>= 3.7
, dicts are insertion ordered
Create a dict
Use
{}
ordict()
Iterate through a dictionary
Iterate through keys:
for k in d
Iterate through values:
for v in d.values()
Iterate through items:
for k, v in d.items()
Copy a dictionary
Same as lists (there are both shallow and deep copying)
Operations on dicts
Regular operations
Get value by key:
d["name"]
,d.get("name")
Count number of elements:
len(d)
Membership checking:
"name" in d
,"John" in d.values()
Inplace operations
Add or update an element:
d["name"] = "Jack"
Delete an element:
del d["name"]
Set default:
d.setdefault("name", "N/A")
Pop an element:
name = d.pop("name")
Update a dict:
d.update(d2)
Dict comprehensions
Similar to list comprehensions
Syntax 1:
{key_expr: value_expr for item in iterable}
Syntax 2:
{key_expr: value_expr for item in iterable if condition}
18.13. Practice#
To be updated