7.1. Dictionaries#

In certain context, lists/tuples have a limitation where you do not know what the “meaning” of each element is. For example, we used days_in_months = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] to represent the the days in months with the assumption that the index corresponds to month digit. Another example, a tuple that represents students,

(
    ('John Doe', 'jdoe@buffalo.edu', 11223344, 'Biology'),
    ('Jane Doe', 'jane@buffalo.edu', 22334455, 'Chemistry'),
)

In both cases you as the programmer know what the data structure holds because you are using it ia specific way.Dictionary is a data structure that allows you to associate a “name” with each value. The months can be represented as

days_in_months = {
    'Jan': 31,
    'Feb': (28,29),
    'Mar': 31,
    'Apr': 30,
    'May': 31,
    'Jun': 30,
    'Jul': 31,
    'Aug': 31,
    'Sep': 30,
    'Oct': 31,
    'Nov': 30,
    'Dec': 31,
}
(
    {
        'Name': 'John Doe', 
        'Email': 'jdoe@buffalo.edu',
        'ID': 11223344, 
        'Major': 'Biology'
    },
    {
        'Name': 'Jane Doe', 
        'Email': 'Jane@buffalo.edu',
        'ID': 22334455, 
        'Major': 'Chemistry'
    },
)
  • The”name is called a “key”

  • The value is called a “value”

  • Together they are called a key-value pair

  • Key is the ‘index’ to access the corresponding value

  • Python dictionary (since v3.6) keep the key values in the order they were inserted

7.1.1. Creating a Dictionary#

  • There are two ways to create a dictionary

7.1.1.1. Method 1#

  • my_dict = {}

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}

7.1.1.2. Method 2#

  • my_dict = dict()

my_dict = dict(
    name='john',
    email='john@email.com',
    id=1234,
    major='Engineering'
)

7.1.2. Accessing a Value#

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}

print(my_dict['name']) # Method 1

key = 'name' # Method 2 -- use a variable key
print(my_dict[key])

7.1.3. Iterating Over a Dictionary#

7.1.3.1. By Values#

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}
for value in my_dict.values():
    print(value)

7.1.3.2. By Keys#

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}
for key in my_dict.keys():
    print(key)

7.1.3.3. Key-Value Pair#

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}
for key, value in my_dict.items():
    print(f'key is {key} and value is {value}')

7.1.4. Checking if a Key Exists#

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}

key = 'Major'
if key in my_dict:
    print(True)
else:
    print(False)

7.1.5. Dictionary Methods#

  • Methods are functions that are attached to a data

7.1.5.1. Empty Dict#

my_dict.clear() ## empty dict

7.1.5.2. Copy a Dict#

  • Creates a SHALLOW COPY

my_dict.copy() # Shallow copy
x = {1: True, 2: [3, 4, 5]}
y = x.copy()
x[1] = False
print(x, y)
x = {1: True, 2: [3, 4, 5]}
y = x.copy()
x[2].append(6)
print(x, y)
  • Create a deep copy using the copy module

import copy
x = {1: True, 2: [3, 4, 5]}
y = copy.deepcopy(x)
x[2].append(6)
print(x, y)

7.1.5.3. Creating dictionary using initial values#

new_student = {}.fromkeys(
    ['name', 'email', 'id', 'major'], 'missing')

my_dict = {}.fromkeys(range(5), 'iammissing')

7.1.5.4. Safely getting a value#

  • If a key does not exist and you try to access it, Python will raise an error. Instead, you can use the get() method to safely get the value, meaning it will return None if the key does not exist. The default is None for missing key, but you can override that.

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}
my_dict.get('name', None) # default
my_dict.get('name', False)
my_dict.get('name', 'defaultname')

7.1.5.5. Removing Values from a Dictionary#

7.1.5.5.1. Method 1#

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}
my_dict.pop('name')

7.1.5.5.2. Method 2#

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}
del my_dict['name']

What happens when you try to remove a key that does not exist?

7.1.5.6. Removing Last Item from the Dictionary#

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}
my_dict.popitem()

7.1.5.7. Updating a Dictionary#

  • Updates over write pre-existing keys

7.1.5.7.1. Method 1#

  • pass in a another dictionary to the .update() method

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}
my_dict.update({'Graduate Year': 2024})

7.1.5.7.2. Method 2#

  • Individually set a value

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}
my_dict['Graduate Year'] = 2024

7.1.5.7.3. Method 3#

  • Remember to save the value!!!

my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}
my_dict | {'Graduate Year': 2024}

print(my_dict)
my_dict = {
    'name': 'john',
    'email': 'john@email.com',
    'id': 1234,
    'major': 'Engineering'
}
my_dict |= {'Graduate Year': 2024}

print(my_dict)

7.1.6. Handing Missing Keys#

  • Say you need to update a key but you do not know if it exists, how would you do it?

my_dict = {'LoginCount': 0}
my_dict['LoginCount'] += 1
my_dict = {'Grades': []}
my_dict['Grades'].append(3)
my_dict = {}
if 'LoginCount' not in my_dict:
    my_dict['LoginCount'] =  0
my_dict['LoginCount'] += 1
my_dict = {}
if 'Grades' not in my_dict:
    my_dict['Grades'] =  []
my_dict['Grades'].append(3)
  • A better way when you know the data type is defaultdict

from collections import defaultdict
my_dict = defaultdict(int)
my_dict['LoginCount'] += 1
from collections import defaultdict
my_dict = defaultdict(list)
my_dict['Grades'].append(3)

7.1.7. Counting#

from collections import Counter
days_in_months = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

Counter(days_in_months)

7.1.8. Dictionary Comprehension#

{ ele:f(ele) for ele in sequence }

{ ele:f(ele) for ele in sequence if condition }

{ ele:f(ele) if condition else g(ele) for ele in sequence }

{ ele:f(ele) for ele in sequence if condition1 and condition2}

7.1.8.1. Examples#

{key: key*value for key, value in my_dict.items()}
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[1], line 1
----> 1 {key: key*value for key, value in my_dict.items()}

NameError: name 'my_dict' is not defined
Hide code cell source
{num: num*num for num in range(5)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
{num: ("even" if num % 2 == 0 else "odd") for num in range(1, 20)}
{1: 'odd',
 2: 'even',
 3: 'odd',
 4: 'even',
 5: 'odd',
 6: 'even',
 7: 'odd',
 8: 'even',
 9: 'odd',
 10: 'even',
 11: 'odd',
 12: 'even',
 13: 'odd',
 14: 'even',
 15: 'odd',
 16: 'even',
 17: 'odd',
 18: 'even',
 19: 'odd'}

7.1.8.1.1. Zip two lists#

list1 = ['john', 'jane', 'doe']
list2 = [95, 99, 98]

{list1[i]: list2[i] for i in range(len(list1))}
{'john': 95, 'jane': 99, 'doe': 98}
dict(zip(list1,list2))
{'john': 95, 'jane': 99, 'doe': 98}