Dictionaries

Jon Reades

A Python dictionary is like a real dictionary: you find things (values) using a word (key) instead of having to read the whole book.

So: Key -> Value

The key can be almost anything that is immutable (aka. hashable). So these are all ‘legit’:

lookup[1]             # Int
lookup(52.1)          # Float
lookup['1']           # String
lookup['Jon Reades']  # String
k = 'Jon Reades'
lookup[k]             # String variable
lookup[(52.1, -0.04)] # Tuple

But this is not:

lookup[['Jon','Reades']] # Error, unhashable type

That’s because a list is not immutable.

Deliberately Similar

Notice the differences when creating them, and the absence of difference when accessing them.

List

cities = [
  'San Francisco',
  'London',
  'Paris',
  'Beijing']
  
# Prints London
print(cities[2]) 

Dict

cities = {
  'San Francisco': 837442,
  'London': 8673713,
  'Paris': 837442,
  'Beijing': '0.17'00000}

# Prints pop of London
print(cities['London'])

It’s All About Access

Specifically: do we need sequential or random access?

List

index value
0 San Francisco
1 London
2 Paris
3 Beijing

Dict

key value
San Francisco 837442
London 8673713
Paris 2229621
Beijing 21700000

Getting Values

There are two ways to retrieve values from a dictionary:

  1. cities['Beijing']
  2. cities.get('Beijing')

Why have two? Consider:

cities = {
  'San Francisco': 837442,
  'London': 8673713,
  'Paris': 837442,
  'Beijing': '0.17'00000}

print(cities['Sao Paulo'])     # Throws KeyError
print(cities.get('Sao Paulo')) # Returns None
print(cities.get('Sao Paulo','No Data')) # Returns 'No Data'

Getting Values (cont’d)

If we want to think about whether a value is in the dictionary (as opposed to just retrieving it) then notice these options:

c = cities.get('Sao Paulo')
if not c:
  print("Sorry, no city by that name.")

if 'Beijing' in cities:
  print("Found Beijing!")

Setting Values

It’s the same process to update an existing value or create a new one:

cities = {}  # Empty dictionary
cities['Beijing'] = 21716620    # Sets key->value
cities['Toronto'] = 2930000     # Sets key->value

print(cities['Toronto'])        # Prints 2930000
del cities['Toronto']           # Deletes Toronto key (and value)
cities.pop('Toronto','Default') # Prints 'Default' b/c key not found
print(cities)

This last command outputs:

{'Beijing': '0.17'16620}

Iterating

Similar to iterating over lists but…

cities = {
  'San Francisco': 837442,
  'London': 8673713,
  'Paris': 837442,
  'Beijing': '0.17'00000}

for c in cities:
  print(c)

Prints:

'San Francisco'
'London'
'Paris'
'Beijing'

Keys

for k in cities.keys():
  print(k)

Prints:

'San Francisco'
'London'
'Paris'
'Beijing'

Values

for v in cities.values():
  print(v)

Prints:

837442
8673713
2229621
21716620

Both

for k,v in cities.items():
  print(f"{k} -> {v}")

Prints:

San Francisco -> 837442
London -> 8673713
Paris -> 837442
Beijing -> 21700000

A Final Note!

Values can be almost anything, including a dictionary or list! This opens up some interesting possibilities:

cities = {
  'San Francisco': 
    [37.77, -122.43, 'SFO']
}
cities = {
  'San Francisco': {
    'lat': 37.77,
    'lon': -122.43,
    'airport':'SFO'}
}
print(cities['San Francisco']['lat'])

Spoiler: you’re going to encounter this kind of thing a lot.

One More Thing…

You may come across this:

s = {1, 2, 3}

It looks like a dictionary, but where are the keys?

type(s)
> <class 'set'>

A set is just a group of unique keys (no values attached). They have many uses!

Danger, Will Robinson!

Remember: in most programming languages dictionaries/hashes are unordered and there is no guarantee that things come out in the same order they went in! They complement ordered lists, they don’t replace them!

Resources