4.1. Mapping Dict

4.1.1. Rationale

  • dict are key-value storage

  • key lookup is very efficient O(1)

  • Mutable - can add, remove, and modify items

4.1.2. Type Definition

  • {} is used more often

  • dict() is more readable

  • Comma after last element is optional

  • Since Python 3.7 dict keeps order of elements

  • Before Python 3.7 dict order is not ensured!!

data = {}
data = dict()

data = {
    1961: 'First Human Space Flight',
    1969: 'First Step on the Moon'}

data = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

data = dict(
    commander='Melissa Lewis',
    botanist='Mark Watney',
    chemist='Alex Vogel')
Listing 4.1. Duplicating items are overridden by latter
data = {
    'commander': 'Melissa Lewis',
    'commander': 'Jan Twardowski',
}
# {'commander': 'Jan Twardowski'}

4.1.3. GetItem

  • [...] throws KeyError exception if key not found in dict

  • .get() returns None if key not found

  • .get() can have default value, if key not found

Listing 4.2. Getitem Method
crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

crew['commander']
# Melissa Lewis

crew['pilot']
# Traceback (most recent call last):
#     ...
# KeyError: 'pilot'
Listing 4.3. Get Method
crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

crew.get('commander')
# Melissa Lewis

crew.get('pilot')
# None

crew.get('pilot', 'not assigned')
# 'not assigned'
Listing 4.4. Getting keys other than str
calendarium = {
    1961: 'First Human Space Flight',
    1969: 'First Step on the Moon'}

calendarium[1961]
# 'First Human Space Flight'

calendarium.get(1961)
# 'First Human Space Flight'

calendarium['1961']
# Traceback (most recent call last):
#     ...
# KeyError: '1961'

calendarium.get('1961')
# None

calendarium.get('1961', 'unknown')
# 'unknown'

4.1.4. Get Keys, Values and Key-Value Pairs

  • Key can be any hashable object

In Python 2, the methods items(), keys() and values() used to "take a snapshot" of the dictionary contents and return it as a list. It meant that if the dictionary changed while you were iterating over the list, the contents in the list would not change. In Python 3, these methods return a view object whose contents change dynamically as the dictionary changes. Therefore, in order for the behavior of iterations over the result of these methods to remain consistent with previous versions, an additional call to list() has to be performed in Python 3 to "take a snapshot" of the view object contents. [Hamidi2017]

crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

list(crew.keys())
# ['commander', 'botanist', 'chemist']

list(crew.values())
# ['Melissa Lewis', 'Mark Watney', 'Alex Vogel']

list(crew.items())
# [('commander', 'Melissa Lewis'),
#  ('botanist', 'Mark Watney'),
#  ('chemist', 'Alex Vogel')]

4.1.5. Set Item

  • Adds if value not exist

  • Updates if value exist

Listing 4.5. Set Item Method
crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

crew['pilot'] = 'Rick Martinez'

print(crew)
# {'commander': 'Melissa Lewis',
#  'botanist': 'Mark Watney',
#  'chemist': 'Alex Vogel',
#  'pilot': 'Rick Martinez'}
Listing 4.6. Update Method
crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

crew.update(pilot='Rick Martinez')
print(crew)
# {'commander': 'Melissa Lewis',
#  'botanist': 'Mark Watney',
#  'chemist': 'Alex Vogel',
#  'pilot': 'Rick Martinez'}

crew.update(mission=['Artemis', 'Ares III'])
print(crew)
# {'commander': 'Melissa Lewis',
#  'botanist': 'Mark Watney',
#  'chemist': 'Alex Vogel',
#  'pilot': 'Rick Martinez',
#  'mission': ['Artemis', 'Ares III']}
Listing 4.7. Update Method
crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

new = {
    'pilot': 'Rick Martinez',
    'surgeon': 'Chris Beck',
    'engineer': 'Beth Johanssen'}

crew.update(new)
print(crew)
# {'commander': 'Melissa Lewis',
#  'botanist': 'Mark Watney',
#  'chemist': 'Alex Vogel',
#  'pilot': 'Rick Martinez',
#  'surgeon': 'Chris Beck',
#  'engineer': 'Beth Johanssen'}

4.1.6. Delete Item

Listing 4.8. Pop Method
crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel',
    'pilot': 'Rick Martinez',
    'surgeon': 'Chris Beck',
    'engineer': 'Beth Johanssen'}

left_alone_on_mars = crew.pop('botanist')

print(crew)
# {'commander': 'Melissa Lewis',
#  'chemist': 'Alex Vogel',
#  'pilot': 'Rick Martinez',
#  'surgeon': 'Chris Beck',
#  'engineer': 'Beth Johanssen'}

print(left_alone_on_mars)
# 'Mark Watney'
Listing 4.9. Popitem Method
crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

last = crew.popitem()

print(crew)
# {'commander': 'Melissa Lewis',
#  'botanist': 'Mark Watney'}

print(last)
# ('chemist', 'Alex Vogel')
Listing 4.10. Del Keyword
crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

del crew['chemist']

print(crew)
# {'commander': 'Melissa Lewis',
#  'botanist': 'Mark Watney'}

4.1.7. GetItem and Slice

  • GetItem with index on dict is not possible

  • Slicing on dict is not possible

crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

crew[0]             # KeyError: 0
crew[1]             # KeyError: 1
crew[2]             # KeyError: 2

crew[-0]            # KeyError: 0
crew[-1]            # KeyError: -1
crew[-2]            # KeyError: -2

crew[1:2]           # TypeError: unhashable type: 'slice'
crew[:2]            # TypeError: unhashable type: 'slice'
crew[::2]           # TypeError: unhashable type: 'slice'
crew = {
    0: 'Melissa Lewis',
    1: 'Mark Watney',
    2: 'Alex Vogel'}

crew[0]             # 'Melissa Lewis'
crew[1]             # 'Mark Watney'
crew[2]             # 'Alex Vogel'

crew[-0]            # 'Melissa Lewis'
crew[-1]            # KeyError: -1
crew[-2]            # KeyError: -2

crew[1:2]           # TypeError: unhashable type: 'slice'
crew[:2]            # TypeError: unhashable type: 'slice'
crew[::2]           # TypeError: unhashable type: 'slice'

4.1.8. Dict or Set

  • Both set and dict keys must be hashable

  • Both set and dict uses the same { and } braces

  • Despite similar syntax, they are different types

{1, 2}            # set
{1: 2}            # dict

{1, 2, 3, 4}      # set
{1: 2, 3: 4}      # dict
Listing 4.11. Empty dict and empty set
data = {1: 1}       # {1:1}
data.pop(1)         # {}

data = {1}          # {1}
data.pop()          # set()
Listing 4.12. Differences
data = {1: 1}
isinstance(data, set)          # False
isinstance(data, dict)         # True

data = {1}
isinstance(data, set)          # True
isinstance(data, dict)         # False

data = {}
isinstance(data, (set, dict))  # True
isinstance(data, set)          # False
isinstance(data, dict)         # True

4.1.9. Length

crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}


len(crew)
# 3

len(crew.keys())
# 3

len(crew.values())
# 3

len(crew.items())
# 3

4.1.10. Examples

git = {
    'ce16a8ce': 'commit/1',
    'cae6b510': 'commit/2',
    '895444a6': 'commit/3',
    'aef731b5': 'commit/4',
    '4a92bc79': 'branch/master',
    'b3bbd85a': 'tag/v1.0',
}

4.1.11. Future

New in version Python: 3.9 PEP 584 merge (|) and update (|=) operators have been added to the built-in dict class.

crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

new = {
    'pilot': 'Rick Martinez',
    'surgeon': 'Chris Beck',
    'engineer': 'Beth Johanssen'}

everyone = crew | new

print(crew)
# {'commander': 'Melissa Lewis',
#  'botanist': 'Mark Watney',
#  'chemist': 'Alex Vogel'}

print(new)
# {'pilot': 'Rick Martinez',
#  'surgeon': 'Chris Beck',
#  'engineer': 'Beth Johanssen'}

print(everyone)
# {'commander': 'Melissa Lewis',
#  'botanist': 'Mark Watney',
#  'chemist': 'Alex Vogel',
#  'pilot': 'Rick Martinez',
#  'surgeon': 'Chris Beck',
#  'engineer': 'Beth Johanssen'}
crew = {
    'commander': 'Melissa Lewis',
    'botanist': 'Mark Watney',
    'chemist': 'Alex Vogel'}

new = {
    'pilot': 'Rick Martinez',
    'surgeon': 'Chris Beck',
    'engineer': 'Beth Johanssen'}

crew |= new

print(crew)
# {'commander': 'Melissa Lewis',
#  'botanist': 'Mark Watney',
#  'chemist': 'Alex Vogel',
#  'pilot': 'Rick Martinez',
#  'surgeon': 'Chris Beck',
#  'engineer': 'Beth Johanssen'}

print(new)
# {'pilot': 'Rick Martinez',
#  'surgeon': 'Chris Beck',
#  'engineer': 'Beth Johanssen'}

4.1.12. Assignments

4.1.12.1. Mapping Dict Define

  • Assignment name: Mapping Dict Define

  • Last update: 2020-10-01

  • Complexity level: easy

  • Lines of code to write: 3 lines

  • Estimated time of completion: 3 min

  • Solution: solution/mapping_dict_define.py

English
  1. Use data from "Input" section (see below)

  2. Create result: dict representing input data

Polish
  1. Użyj danych z sekcji "Input" (patrz poniżej)

  2. Stwórz result: dict reprezentujący dane wejściowe

Input
First Name: Jan
Last Name: Twardowski
Missions: Apollo, Artemis

4.1.12.2. Mapping Dict Items

  • Assignment name: Mapping Dict Items

  • Last update: 2020-10-01

  • Complexity level: easy

  • Lines of code to write: 3 lines

  • Estimated time of completion: 3 min

  • Solution: solution/mapping_dict_items.py

English
  1. Use data from "Input" section (see below)

  2. Print list of DATA keys

  3. Print list of DATA values

  4. Print list of DATA key-value pairs

  5. Compare result with "Output" section (see below)

Polish
  1. Użyj danych z sekcji "Input" (patrz poniżej)

  2. Wypisz listę kluczy z DATA

  3. Wypisz listę wartości z DATA

  4. Wypisz listę pary klucz-wartość z DATA

  5. Porównaj wyniki z sekcją "Output" (patrz poniżej)

Input
DATA = {
    'Sepal length': 5.8,
    'Sepal width': 2.7,
    'Petal length': 5.1,
    'Petal width': 1.9,
}
Output
keys: list
# ['Sepal length', 'Sepal width', 'Petal length', 'Petal width']

values: list
# [5.8, 2.7, 5.1, 1.9]

items: list[tuple]
# [('Sepal length', 5.8),
#  ('Sepal width', 2.7),
#  ('Petal length', 5.1),
#  ('Petal width', 1.9)]

4.1.12.3. Mapping Dict Substitute

  • Assignment name: Mapping Dict Substitute

  • Last update: 2020-10-01

  • Complexity level: easy

  • Lines of code to write: 3 lines

  • Estimated time of completion: 5 min

  • Solution: solution/mapping_dict_substitute.py

English
  1. Use data from "Input" section (see below)

  2. Ask user to input single letter

  3. Convert to lowercase

  4. If letter is in PL then use conversion value as letter

  5. Print letter

Polish
  1. Użyj danych z sekcji "Input" (patrz poniżej)

  2. Poproś użytkownika o wprowadzenie jednej litery

  3. Przekonwertuj literę na małą

  4. Jeżeli litera jest w PL to użyj przekonwertowanej wartości jako litera

  5. Wypisz literę

Input
PL = {'ą': 'a', 'ć': 'c', 'ę': 'e',
      'ł': 'l', 'ń': 'n', 'ó': 'o',
      'ś': 's', 'ż': 'z', 'ź': 'z'}
Example
| Input | Output |
|-------|--------|
|   A   |    a   |
|   x   |    x   |
|   ś   |    s   |
|   Ź   |    z   |

4.1.12.4. Mapping Dict Get

  • Assignment name: Mapping Dict Get

  • Last update: 2020-10-01

  • Complexity level: easy

  • Lines of code to write: 3 lines

  • Estimated time of completion: 5 min

  • Solution: solution/mapping_dict_get.py

English
  1. Use data from "Input" section (see below)

  2. Create translator of pilot's alphabet

  3. Each letter has it's phonetic counterpart

  4. To convert table use multiline select with alt key in your IDE (if shortcut key is not working in your IDE, use only first four letters)

  5. Ask user to input letter

  6. User will always put only one capitalized letter or number

  7. Print phonetic letter pronunciation

  8. If user type character not existing in alphabet, print: "Pilots don't say that"

  9. Do not use if, try, and except

Polish
  1. Użyj danych z sekcji "Input" (patrz poniżej)

  2. Stwórz tłumacza alfabetu pilotów

  3. Pojedynczym literom przyporządkuj ich fonetyczne odpowiedniki

  4. Do przekonwertowania tabelki wykorzystaj zaznaczanie wielu linijek za pomocą klawisza alt w Twoim IDE (jeżeli skrót klawiszowy nie działa w Twoim IDE, użyj tylko cztery pierwsze litery)

  5. Poproś użytkownika o wprowadzenie litery

  6. Użytkownik zawsze poda tylko jedną dużą literę lub cyfrę

  7. Wypisz fonetyczną wymowę litery

  8. Jeżeli wpisał znak, który nie występuje w alfabecie, wypisz: "Pilots don't say that"

  9. Nie używaj if, try ani except

Input
Letter, Pronounce
A, Alfa
B, Bravo
C, Charlie
D, Delta
E, Echo
F, Foxtrot
G, Golf
H, Hotel
I, India
J, Juliet
K, Kilo
L, Lima
M, Mike
N, November
O, Oscar
P, Papa
Q, Quebec
R, Romeo
S, Sierra
T, Tango
U, Uniform
V, Victor
W, Whisky
X, X-Ray
Y, Yankee
Z, Zulu
The whys and wherefores
  • Defining dict with values

  • Type casting

4.1.13. References

Hamidi2017

Frédéric Hamidi. Why does Python 3 need dict.items to be wrapped with list()? https://stackoverflow.com/a/17695716