A dictionary is an example of a key value store also known as Mapping in Python. It allows you to store and retrieve elements by referencing a key. As dictionaries are referenced by key, they have very fast lookups. As they are primarily used for referencing items by key, they are not sorted.
Rules to create a dictionary:
# Creating and populating it with values
stock = {'eggs': 5, 'milk': 2}
# Or creating an empty dictionary
dictionary = {}
# And populating it after
dictionary['eggs'] = 5
dictionary['milk'] = 2
# Values can also be lists
mydict = {'a': [1, 2, 3], 'b': ['one', 'two', 'three']}
# Use list.append() method to add new elements to the values list
mydict['a'].append(4) # => {'a': [1, 2, 3, 4], 'b': ['one', 'two', 'three']}
mydict['b'].append('four') # => {'a': [1, 2, 3, 4], 'b': ['one', 'two', 'three', 'four']}
# We can also create a dictionary using a list of two-items tuples
iterable = [('eggs', 5), ('milk', 2)]
dictionary = dict(iterables)
# Or using keyword argument:
dictionary = dict(eggs=5, milk=2)
# Another way will be to use the dict.fromkeys:
dictionary = dict.fromkeys((milk, eggs)) # => {'milk': None, 'eggs': None}
dictionary = dict.fromkeys((milk, eggs), (2, 5)) # => {'milk': 2, 'eggs': 5}
Using built-in class: dict
mydict1 = dict()
mydict2 = dict(key='value')
mydict3 = dict([('key', 'value')])
# make a shallow copy of another dict (only when the keys are ONLY strings!)
mydict4 = dict(**otherdict)
from collections import OrderedDict
mydict = OrderedDict()
mydict['first'] = 1
mydict['second'] = 2
mydict['third'] = 3
mydict['last'] = 4
# Outputs "first 1", "second 2", "third 3", "last 4"
for key in mydict:
print(key, mydict[key])
To add items to your dictionary, you can simply create a new key with a value:
mydict['new_key'] = 'new_value'
But if you want to add more key->value pairs at once, you must use the .update()
method:
mydict.update({
'name': 'John Doe', # the value is a string
'age': 25, # the value is a number (integer)
'volunteer_years': [2014, 2016, 2017], # the value is a list
'birth_date': { # the value is another dictionary
'year': 1990,
'month': 'June',
'day': 10
}
})
To delete an item from a dictionary use the del
statement and provide the key of the dictionary:
del mydict['volunteer_years']
Many times it can happen that you will access a non-existent key, which will result in a KeyError
exception:
mydict = {}
mydict['not-here']
The exception will be:
Traceback (most recent call last):
File "/path/to/my-python-file.py", line 1, in <module>
mydict['not-here']
KeyError: 'not-here'
To avoid this error, you must use the dict.get
method which allows you to have a default value to return in case of the absent key:
value = mydict.get(key, default_value=None)
And as a working example, you'll have:
myvalue1 = mydict.get('mykey1') # will return None if the key does not exists
myvalue2 = mydict.get('mykey2', 'my-default-value') # will return string 'my-default-value' if the key does not exists
Catch the exception and return the default value
try:
value = mydict[key]
except KeyError:
value = my_default_value
You can also check if the key exists in the dictionary:
if key in mydict:
value = mydict[key]
else:
value = default_value
If you use the dictionary as an iterator (it means in a for
loop statement), it will traverse the keys of the dictionary and you will be able to get the values through the key:
mydict = {
'a': 1,
'b': 2,
'c': 3,
}
for key in mydict:
print(key, mydict[key])
# a 1
# b 2
# c 3
The same is true when usef in a comprehension
print([key for key in mydict])
# ['a', 'b', 'c']
You also can loop through both the key and value simultaneously, by using mydict.items()
method:
for key, value in mydict.items():
print(key, value)
# a 1
# b 2
# c 3
If you need only the keys, you will use the method mydict.keys()
in the same manner. The same will be for the values, by using mydict.values()
The methodskeys()
,values()
,items()
will return lists, whileiterkeys()
,itervalues()
anditeritems()
will return iterators.
This will be available in standard library as defaultdict
. Being in standard library means that you don't need to install anything with pip or poetry
from collections import defaultdict
mydict = defaultdict(int)
mydict['one']
mydict['two'] = 6
mydict['three']
print(mydict) # --> defaultdict(<class 'int'>, {'one': 0, 'two': 6, 'three': 0})
As you can see, if you don't add a value to the key, by default will be 0 assigned in this case. But the same you can do with a lambda to add a string
from collections import defaultdict
mydict = defaultdict(lambda: 'mystring')
mydict['one']
mydict['two'] = 6
mydict['three'] = 'my third element'
mydict['four']
print(mydict) # --> defaultdict(<function <lambda> at 0x104abc3a0>, {'one': 'mystring', 'two': 6, 'three': 'my third element', 'four': 'mystring'})
Consider the following dictionaries
fish = {'name': 'Nemo', 'hands': 'fins', 'special': 'gills'}
dog = {'name': 'Lassie', 'hands': 'paws', 'color': 'brown'}
fishdog = {**fish, **dog} # you can have more dictionaries here as well
# fishdog = {'name': 'Lassie', 'hands': 'paws', 'special': 'gills', 'color': 'brown'}
In this example you can see that the duplicated keys map to their latter-most value. For example "paws" overrides "fins"
If you want to keep the first values and only add new ones that don't exist, use the following example:
from collections import ChainMap
fishdog = dict(ChainMap(fish, dog))
# fishdog = {'name': 'Nemo', 'hands': 'fins', 'color': 'brown', 'special': 'gills'}
Using dict.update
will override the existing keys-values with the new ones
Let's say we have the following dictionary:
mydict = {
'brand': 'BMW',
'model': 'R 1250 GS',
'year': 2022,
'color': 'Triple Black',
'engine': {
'cylinders': 2,
'capacity': 1254,
'power': {
'kw': 100,
'hp': 136,
'rev': 7750
},
'torque': {
'nm': 143,
'rev': 6250
}
},
'length': {
'number': 2207,
'unit': 'mm'
},
'height': {
'number': 1430,
'unit': 'mm'
},
'width': {
'number': 249,
'unit': 'kg'
},
'packages': ['Dynamic Packet', 'Enduro Packet', 'Lights Packet', 'Comfort Packet', 'Touring Packet']
}
Here are some examples on how to access the values from the above dictionary:
# Get the Brand
print(mydict['brand']) # or mydict.get('brand')
# Get the Model
print(mydict['model'])
# Get the Engine capacity
print(mydict['engine']['capacity'])
# Get the engine HorsePower
print(mydict['engine']['power']['hp'])
# Get the third package: Lights Packet
print(mydict['packages'][2]) # yes, it is correct, list indexing starts from zero (0)