Python Dictionaries
Tags: python, beginners, ebook, exercises
Published: 2021-01-23 13:35:25

---
title: "Python Dictionaries"
published: true
description: "Python dict data type, methods and operations"
canonical_url: https://learnbyexample.github.io/100_page_python_intro/dict.html
series: 100 Page Python Intro
tags: Python,beginner,ebook,exercises
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/x0gbxspe60srzezgp6gd.png
---

Dictionaries can be thought of as a collection of **key-value** pairs or a **named list of items**. It used to be unordered, but recent Python versions ensure that the insertion order is maintained.

## Initialization and accessing elements

A `dict` data type is declared within `{}` characters and each item requires two values — an immutable data type for key, followed by `:` character and finally a value of any data type. The elements are separated by a comma character, just like the other container types.

To access an element, the syntax is `dict_variable[key]`. Retrieving an item takes a constant amount of time, irrespective of the size of the `dict` (see [Hashtables](https://greenteapress.com/thinkpython2/html/thinkpython2022.html#sec255) for details). Dictionaries are mutable, so you can change an item's value, add items, remove items, etc.

```python
>>> marks = {'Rahul': 86, 'Ravi': 92, 'Rohit': 75, 'Rajan': 79}

>>> marks['Rohit']
75
>>> marks['Rahul'] += 5
>>> marks['Ram'] = 67 
>>> del marks['Rohit']

# note that the insertion order is maintained
>>> marks
{'Rahul': 91, 'Ravi': 92, 'Rajan': 79, 'Ram': 67}
```

Here's an example with `list` and `tuple` keys.

```python
>>> list_key = {[1, 2]: 42}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

>>> items = {('car', 2): 'honda', ('car', 5): 'tesla', ('bike', 10): 'hero'}
>>> items[('bike', 10)]
'hero'
```

You can also use the [dict()](https://docs.python.org/3/library/functions.html#func-dict) function for initialization in various ways. If all the keys are of `str` data type, you can use the same syntax as keyword arguments seen earlier with function definitions. You can also pass a container type having two values per element, such as a `list` of `tuples` as shown below.

```python
>>> marks = dict(Rahul=86, Ravi=92, Rohit=75, Rajan=79)
>>> marks
{'Rahul': 86, 'Ravi': 92, 'Rohit': 75, 'Rajan': 79}

>>> items = [('jeep', 20), ('car', 3), ('cycle', 5)]
>>> dict(items)
{'jeep': 20, 'car': 3, 'cycle': 5}
```

Another way to initialize is to use the `fromkeys()` method that accepts an iterable and an optional value (default is `None`). The same value will be assigned to all the keys, so be careful if you want to use a mutable object, since the same reference will be used as well.

```python
>>> colors = ('red', 'blue', 'green')

>>> dict.fromkeys(colors)
{'red': None, 'blue': None, 'green': None}
>>> dict.fromkeys(colors, 255)
{'red': 255, 'blue': 255, 'green': 255}
```

## get and setdefault

If you try to access a `dict` key that doesn't exist, you'll get a `KeyError` exception. If you do not want an exception to occur, you can use the `get()` method. By default it'll return a `None` value for keys that do not exist, which you can change by providing a default value as the second argument.

```python
>>> marks = dict(Rahul=86, Ravi=92, Rohit=75, Rajan=79)

>>> marks['Ron']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Ron'

>>> marks.get('Ravi')
92
>>> value = marks.get('Ron')
>>> print(value)
None
>>> marks.get('Ron', 0)
0
```

Here's a more practical example:

```python
>>> vehicles = ['car', 'jeep', 'car', 'bike', 'bus', 'car', 'bike']
>>> hist = {}
>>> for v in vehicles:
...     hist[v] = hist.get(v, 0) + 1
... 
>>> hist
{'car': 3, 'jeep': 1, 'bike': 2, 'bus': 1}
```

Using `get()` method will not automatically add keys that do not exist yet to the `dict` object. You can use `setdefault()` method, which behaves similarly to `get()` except that keys will get created if not found. See also [docs.python: collections.defaultdict](https://docs.python.org/3/library/collections.html#collections.defaultdict).

```python
>>> marks = dict(Rahul=86, Ravi=92, Rohit=75, Rajan=79)

>>> marks.get('Ram', 40)
40
>>> marks
{'Rahul': 86, 'Ravi': 92, 'Rohit': 75, 'Rajan': 79}

>>> marks.setdefault('Ram', 40)
40
>>> marks
{'Rahul': 86, 'Ravi': 92, 'Rohit': 75, 'Rajan': 79, 'Ram': 40}
```

## Iteration

The default `for` loop over a `dict` object will give you a key for each iteration.

```python
>>> fruits = dict(banana=12, papaya=5, mango=10, fig=100)

>>> for k in fruits:
...     print(f'{k}:{fruits[k]}')
... 
banana:12
papaya:5
mango:10
fig:100

# you'll also get only the keys if you apply list(), tuple() or set()
>>> list(fruits)
['banana', 'papaya', 'mango', 'fig']
```

As an exercise,

* given `fruits` dictionary as defined in the above code snippet, what do you think will happen when you use `a, *b, c = fruits`?
* given `nums = [1, 4, 6, 22, 3, 5, 4, 3, 6, 2, 1, 51, 3, 1]`, keep only first occurrences of a value from this list without changing the order of elements. You can do it with `dict` features presented so far. `[1, 4, 6, 22, 3, 5, 2, 51]` should be the output. See [Using dict to eliminate duplicates while retaining order](https://twitter.com/raymondh/status/944125570534621185) if you are not able to solve it.

## Dict methods and operations

The `in` operator checks if a key is present in the given dictionary. The `keys()` method returns all the keys and `values()` method returns all the values. These methods return a custom set-like object, but with insertion order maintained.

```python
>>> marks = dict(Rahul=86, Ravi=92, Rohit=75, Rajan=79)

>>> 'Ravi' in marks
True
>>> 'Ram' in marks
False

>>> marks.keys()
dict_keys(['Rahul', 'Ravi', 'Rohit', 'Rajan'])

>>> marks.values()
dict_values([86, 92, 75, 79])
```

The `items()` method can be used to get a key-value `tuple` for each iteration.

```python
>>> fruits = dict(banana=12, papaya=5, mango=10, fig=100)

# set-like object
>>> fruits.items()
dict_items([('banana', 12), ('papaya', 5), ('mango', 10), ('fig', 100)])

>>> for fruit, qty in fruits.items():
...     print(f'{fruit}\t: {qty}')
... 
banana  : 12
papaya  : 5
mango   : 10
fig     : 100
```

The `del` statement example seen earlier removes the given key without returning the value associated with it. You can use the `pop()` method to get the value as well. The `popitem()` method removes the last added item and returns the key-value pair as a `tuple`.

```python
>>> marks = dict(Rahul=86, Ravi=92, Rohit=75, Rajan=79)

>>> marks.pop('Ravi')
92
>>> marks
{'Rahul': 86, 'Rohit': 75, 'Rajan': 79}

>>> marks.popitem()
('Rajan', 79)
>>> marks
{'Rahul': 86, 'Rohit': 75}
```

The `update()` method allows you to add/update items from another dictionary or a container with key-value pair elements.

```python
>>> marks = dict(Rahul=86, Ravi=92, Rohit=75, Rajan=79)
>>> marks.update(dict(Jo=89, Joe=75, Ravi=100))
# note that 'Ravi' has '100' as the updated value
>>> marks
{'Rahul': 86, 'Ravi': 100, 'Rohit': 75, 'Rajan': 79, 'Jo': 89, 'Joe': 75}

>>> fruits = dict(banana=12, papaya=5, mango=10, fig=100)
>>> fruits.update([('onion', 3), ('pea', 10)])
>>> fruits
{'banana': 12, 'papaya': 5, 'mango': 10, 'fig': 100, 'onion': 3, 'pea': 10}
```

The `|` operator is similar to the `update()` method, except that you get a new `dict` object instead of in-place modification.

```python
>>> d1 = {'banana': 12, 'papaya': 5, 'mango': 20}
>>> d2 = {'mango': 10, 'fig': 100}

# this used to be done using unpacking, i.e. {**d1, **d2}
>>> d1 | d2
{'banana': 12, 'papaya': 5, 'mango': 10, 'fig': 100}
```

## Arbitrary keyword arguments

To accept arbitrary number of keyword arguments, use `**var_name` in the function definition. This has to be declared the last, after all the other types of arguments. Idiomatically, `**kwargs` is used as the variable name. See [stackoverflow: Decorators demystified](https://stackoverflow.com/questions/739654/how-to-make-function-decorators-and-chain-them-together/1594484#1594484) for a practical use case of arbitrary keyword arguments.

```python
>>> def many(**kwargs):
...     print(f'{kwargs = }')
... 
>>> many()
kwargs = {}
>>> many(num=5)
kwargs = {'num': 5}
>>> many(car=5, jeep=25)
kwargs = {'car': 5, 'jeep': 25}
```

Turning it around, when you have a function defined with keyword arguments, you can unpack a dictionary while calling the function.

```python
>>> def greeting(phrase='hello', style='='):
...     print(f'{phrase:{style}^{len(phrase)+6}}')
... 
>>> greeting()
===hello===
>>> d = {'style': '-', 'phrase': 'have a nice day'}
>>> greeting(**d)
---have a nice day---
```