Mapping Types

Indices and tables

Definition

A mapping is a container type that stores a collection of zero or more key-value pairs. The keys must be hashable, but the values can be any arbitrary Python object.

Values need not all be the same type, and values can nest other container types.

Values in a mapping are indexed by key using the item access operator [].

Dict

MUTABILITY: Mutable

The dict (dictionary) is currently the only intrinsic mapping type defined by the Python data model.

Items in a dictionary are stored unordered.

Since dictionaries are mutable, you can modify the keys and values after creation without forcing Python to create a new object.

Dictionaries can be constructed in a variety of ways:

  • Using curly brackets {}. For example:

    To create a dictionary with 0 items:

    >>> foo = {}
    >>> foo
    {}
    

    To create a dictionary from key-value pairs using : as the separator:

    >>> foo = {'a': 1, 'b': 2, 'c': 3}
    >>> foo
    {'a': 1, 'b': 2, 'c': 3}
    
  • Using an expression in curly brackets {} to create a dict comprehension. For example:

    >>> foo = {'jim jones': ('Eng', 100),
    ...        'bim bartman': ('Eng', 341),
    ...        'jake king': ('Eng', 99),
    ...        'kyle zapp': ('Mkt', 921),
    ...        'moon yee': ('Mkt', 472),
    ...        'sun tzu': ('Mkt', 8294),
    ...        'tick tock': ('Fin', 46)}
    >>> bar = {key.title(): val[0] for key, val in foo.items()}
    >>> bar
    {'Bim Bartman': 'Eng',
     'Jake King': 'Eng',
     'Jim Jones': 'Eng',
     'Kyle Zapp': 'Mkt',
     'Moon Yee': 'Mkt',
     'Sun Tzu': 'Mkt',
     'Tick Tock': 'Fin'}
    
    >>> baz = {key.title(): val[1] for key, val in foo.items() if val[0] == "Mkt"}
    >>> baz
    {'Kyle Zapp': 921,
     'Moon Yee': 472,
     'Sun Tzu': 8294}
    
  • Using the dict constructor, which allows you to do several things:

    With no arguments, it creates and empty dictionary:

    >>> foo = dict()
    >>> foo
    {}
    

    With arguments passed as keywords, it uses the first as the key and the second as the value:

    >>> foo = dict(a=1, b=2, c=3)
    >>> foo
    {'a': 1, 'b': 2, 'c': 3}
    

    Note

    You can only use keyword arguments to the dict constructor if the keys are considered valid Python identifiers. For example, the key, “jim bob” is not a valid Python identifier and it’s use would result in a SyntaxError being thrown.

    When passed a sequence, where each item in the sequence is itself a sequence of 2 objects, it builds the dictionary using the first object as the key and the second as the value:

    >>> foo = dict([('a', 1), ('b', 2), ('c', 3))
    >>> foo
    {'a': 1, 'b': 2, 'c': 3}
    

    When passed a dictionary, this is one way of shallow-copy ing the dictionary:

    >>> foo = {'a': 1, 'b': 2, 'c': 3}
    >>> bar = dict(foo)
    >>> bar
    {'a': 1, 'b': 2, 'c': 3}
    

Individual items in a mapping can be indexed using the item access operator [], which takes a key, as in, [key].

If key doesn’t exist, you will get a KeyError.

Tip

To avoid getting a KeyError for keys that don’t exist, you can use the collections.defaultdict type, which has all the same methods as the dict class, but, allows you to specify a default value to use for keys that don’t exist. If an attempt is made to access the dictionary using a key that doesn’t exist, the key is created and the value set to the default value. For example:

>>> import collections
>>> foo = collections.defaultdict(int)
>>> foo['a']
>>> foo['b']
>>> foo
defaultdict(int, {'a': 0, 'b': 0})

Due to the fact that mappings store unordered items, it is not possible to slice or stride them.

Dictionaries compare equal if the have the same key:value pairs. For example:

>>> foo = {'a': 1, 'b': 2, 'c': 3}
>>> bar = {'b': 2, 'c': 3, 'a': 1}
>>> baz = {'d': 4, 'e': 5, 'f': 6}
>>> bif = {'a': 1, 'b': 2}
>>> foo == bar
True
>>> foo == baz
False
>>> foo == bif
False

Dictionaries don’t support comparing using <, <=, > and >=.

Dict Specific Methods

The dict type supports the operations shown in Table 11.

Table 11 Table of Dict Specific Operations
Operation Description
len(d)

Return the number of items in the dictionary d.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> len(foo)
5
d[key]

Return the item of d with key key.

Raises KeyError if key in not in map.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> foo['a']
1
d[key] = val

Sets key in d to val.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> foo['a'] = 99
>>> foo
{'a': 99, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
del d[key]

Remove the item of d with key key.

Raises KeyError if key in not in map.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> del foo['a']
>>> foo
{'b': 2, 'c': 3, 'd': 4, 'e': 5}
key in d

Membership testing. Returns True if key is in d.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> 'a' in foo
True
key not in d

Membership testing. Returns True if key is not in d.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> 'z' not in foo
True
iter(d)

Returns an iterator over the keys of the dictionary.

Allows dict objects to be iterated over using for loops.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> for key in foo:
...     print("{}:{}".format(key, foo[key]))
b:2
c:3
d:4
e:5
a:1
d.items()

Return a new view of the dictionary’s items (its (key, value) pairs).

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> foo.items()
 dict_items([('b', 2), ('c', 3), ('d', 4), ('e', 5), ('a', 1)])
>>> list(foo.items())
[('b', 2), ('c', 3), ('d', 4), ('e', 5), ('a', 1)]
>>> for item in foo.items():
...     print(item)
('b', 2)
('c', 3)
('d', 4)
('e', 5)
('a', 1)
d.keys()

Returns a view of the dictionary’s keys.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> foo.keys()
dict_keys(['b', 'c', 'd', 'e', 'a'])
>>> list(foo.keys())
['b', 'c', 'd', 'e', 'a']
>>> for key in foo.keys():
...    print(key)
b
c
d
e
a
d.values()

Return a new view of the dictionary’s values.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> foo.values()
dict_values([2, 3, 4, 5, 1])
>>> list(foo.values())
[2, 3, 4, 5, 1]
>>> for val in foo.values():
...    print(val)
2
3
4
5
1
d.clear()

Removes all items from the dictionary d.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> foo.clear()
>>> foo
{}
d1 = d0.copy()

Return a shallow copy of dictionary d0.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> bar = foo.copy()
>>> bar
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
dict.fromkeys(seq[, val])

Create new dictionary with keys from seq and values set to val.

>>> foo = dict.fromkeys(['a', 'b', 'c'], 1)
>>> foo
{'a': 1, 'b': 1, 'c': 1}
d.get(key[, default])

Return the value for key if key is in the dict, else default.

Never raises KeyError as default default is None.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> foo.get('f', 99)
99
d.pop(key[, default])

If key is in the dictionary, remove it and return its value.

If not, return default.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> foo.pop('c')
3
>>> foo
{'a': 1, 'b': 2, 'd': 4, 'e': 5}
d.popitem()

Remove and return an arbitrary (key, value) pair from the dictionary.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> foo.popitem()
('b', 2)
>>> foo
{'a': 1, 'c': 3, 'd': 4, 'e': 5}
d.setdefault(key[, default])

If key is in the dictionary, return its value.

If not, insert key with a value of default and return default.

default defaults to None.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> foo.setdefault('f', 99)
99
>>> foo
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 99}
d.update([x])

Update the dictionary d with the key/value pairs from x.

Existing keys are overwritten.

x can be a dict, a sequence of key/val pairs, or keyword arguments.

>>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> foo.update({'f': 6})
>>> foo.update([('g', 7), ('h', 8)])
>>> foo.update(i=9)
>>> foo
{'a': 1,
 'b': 2,
 'c': 3,
 'd': 4,
 'e': 5,
 'f': 6,
 'g': 7,
 'h': 8,
 'i': 9}

The methods, items(), keys() and values() return dictionary view objects. These are read-only objects that can be iterated over and who’s content changes when the underlying dictionary changes.

The advantage to dictionary view objects is they allow set type operations on them if their contents are unique.

Note

Dictionary keys are always unique. Dictionary values may or may not be unique. Dictionary items are unique only if keys and values are all unique.

For example:

  • Union (return a new set with elements from the set and all others)

    >>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
    >>> bar = {'a': 99, 'f': 6, 'g': 7}
    >>> bif = {'a': 200, 'c': 444, 'h': 555}
    >>> foo.keys() | bar.keys() | bif.keys()
    {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
    
  • Intersection (return a new set with elements common to the set and all others)

    >>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
    >>> bar = {'a': 99, 'f': 6, 'g': 7}
    >>> bif = {'a': 200, 'c': 444, 'h': 555}
    >>> foo.keys() & bar.keys() & bif.keys()
    {'a'}
    
  • Difference (return a new set with elements in the set that are not in the others)

    >>> foo = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
    >>> bar = {'a': 99, 'f': 6, 'g': 7}
    >>> bif = {'a': 200, 'c': 444, 'h': 555}
    >>> foo.keys() - bar.keys() - bif.keys()
    {'b', 'd', 'e'}
    

Try it!

Try the following:

  • Create an empty dict.

  • Add the following key:value pairs to the empty dict you just created:

    • ‘girls’ : 3
    • ‘boys’ : 5
    • ‘dogs’ : 1
  • Copy the following dictionary:

     {'John'  : ('Hamilton',   20),
      'Sam'   : ('Hamilton',   32),
      'Cass'  : ('Toronto',    52),
      'Nathan': ('Toronto',    36),
      'Alison': ('Hamilton',   27),
      'Erin'  : ('Toronto',    43),
      'Kevin' : ('Burlington', 62),
      'Julia' : ('Toronto',    58)
    }
    
  • Get the keys from the copy of the dictionary above.

  • Remove “Nathan” from the copy of the dictionary above.

  • Merge the first dictionary above with the copy of the dictionary above.