Most people are familiar with list comprehensions but they are not aware that a similar syntax exist for dictionaries as well.

The comprehension syntax combines the features of looping, conditional execution and sequence building all into a single concise syntax.

The primary goal of all comprehension syntaxes is to create and populate an object e.g list or dictionary from the elements of another iterable.

Consider the following basic example of list comprehension.

ExampleEdit & Run

with list comprehension 

L = [n for n in range(20) if n%2==0]

print(L)
copy
Output:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18] [Finished in 0.010300727095454931s]

In the above example, list L is  created and populated with numbers from the range iterable i.e range(20).The condition if n % 2 == 0 applies a filter which ensures that only even numbers are added to the list. As you can easily tell, the above syntax is more convenient and expressive than the alternative approach i.e without using list comprehension.

ExampleEdit & Run

without list comprehension

L = []

for n in range(20):
  if n%2==0:
      L.append(n)

print(L)
copy
Output:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18] [Finished in 0.009943754877895117s]

How dictionary comprehension works

Dictionary comprehension syntax

A dictionary stores key/value pairs and each pair is known as an item.   When writing dictionaries, the key and the value are separated with a colon, while the items themselves are separated with a comma.

ExampleEdit & Run
D = {1: 1, 2: 4, 3: 9, 4: 16}

print(D)
copy
Output:
{1: 1, 2: 4, 3: 9, 4: 16} [Finished in 0.009392163716256618s]

Dictionary comprehension syntax is slightly different from other forms of comprehensions in order to suit the unique syntax of dictionaries.

Consider if we want to create a dictionary of numbers and their squares in a given range. Without dictionary comprehension, we can do it  as shown below:

ExampleEdit & Run

without comprehension 

D = {}

for num in range(1, 11):
   D[num] = num ** 2

print(D)
copy
Output:
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100} [Finished in 0.009761057794094086s]

The above example can be put into just a single line with dictionary comprehension, as shown below:

ExampleEdit & Run

with comprehension 

D = {num: num ** 2 for num in range(1, 11)}

print(D)
copy
Output:
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100} [Finished in 0.009212445933371782s]

The Dictionary Comprehension Syntax

The basic syntax of dictionary comprehension looks as shown below:

Syntax:
{key: value for vars in <iterable>}
copy

Any valid expression can be placed in the key and value parts, the resulting object after evaluation will be inserted as the key( or value) of the dictionary item. Consider the following example:

ExampleEdit & Run
data = ('Apple', 'Melon', 'Mango')

D = {word.upper(): ''.join(reversed(word)) for word in data}

print(D)
copy
Output:
{'APPLE': 'elppA', 'MELON': 'noleM', 'MANGO': 'ognaM'} [Finished in 0.010206392966210842s]

The above example is used to demonstrate that we can put any valid expressions in the key and value sections of the comprehension. 

The vars represents aliases for elements in the target iterable, you can alias as many elementss as necessary depending on  the nature of the iterable.

Consider the following example:

ExampleEdit & Run
data = [('zero', 'null'), ('one', 'eins'), ('two', 'zwei')]

D = {english: german for english, german in data}

print(D)
copy
Output:
{'zero': 'null', 'one': 'eins', 'two': 'zwei'} [Finished in 0.009359255898743868s]

In the above example, the  iterable is a list of two-length tuples . We used the two variables i.e english and german to alias the tuple elements. Note that this is an application of unpacking and should be familiar if you understand how unpacking works.

We can also build a dictionary with elements from another dictionary by using the items() method to get the (key, value) tuples of the original dictionary. Consider the following example.

ExampleEdit & Run
original = {0: 'zero', 1:'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:'six'}

D = {key: value for key, value in original.items()}

print(D)
copy
Output:
{0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six'} [Finished in 0.009335396811366081s]

Advanced dictionary comprehension syntax

In the previous section we have seen the basic syntax of dictionary comprehension, however,  we can build more complex comprehension statements. In this section we will look at more features we can add to make the comprehension logic more expressive.

Comprehension with conditions

We can add conditions to make the picking of the elements more restrictive. This can be used to apply filters so that only the elements that satisfies the condition(s) are picked.

Conditions comes at the rightmost end after other parts. The syntax is as shown below:

Syntax:
{key: value for vars in iterable if <condition>}
copy

Consider the following example:

ExampleEdit & Run
D = {num: num ** 2 for num in range(1, 21) if num % 2 == 1}

print(D)
copy
Output:
{1: 1, 3: 9, 5: 25, 7: 49, 9: 81, 11: 121, 13: 169, 15: 225, 17: 289, 19: 361} [Finished in 0.009584795217961073s]

In the above example, we have included a condition so that only even numbers are picked in the iterable.

Multiple conditions can be chained using multiple if statements. For example consider if we want only the numbers which are divisible with both 2 and  3 to picked. We can use two if statements as follows:

ExampleEdit & Run
D = {num: num ** 2 for num in range(1, 21) if (num % 2 == 0) if (num % 3 == 0) }

print(D)
copy
Output:
{6: 36, 12: 144, 18: 324} [Finished in 0.009670587722212076s]

Note that there are two if statements in the condition, you can have as many of them as necessary. However, it would be wise to avoid making the comprehension unnecessarily complex. For example, in the above case, we could as well have achieved the same by using a single if with an and clause to merge the conditions, as shown below:

ExampleEdit & Run
D = {num: num ** 2 for num in range(1, 21) if (num % 2 == 0 and num % 3 == 0) }

print(D)
copy
Output:
{6: 36, 12: 144, 18: 324} [Finished in 0.009346781764179468s]

Comprehension with multiple for loops

Nested for loops can be achieved in the comprehension by chaining Multiple for statement.

ExampleEdit & Run
nums = [1, 2, 3]
letters = ['a', 'b', 'c']

D = {print(letter, end = ' '): print(num, end = ' ')  for letter in letters for num in nums}
copy
Output:
a 1 a 2 a 3 b 1 b 2 b 3 c 1 c 2 c 3  [Finished in 0.009354411158710718s]

As shown above, multiple for statements will lead to nested for loops.

Conclusion

  • The dictionary comprehension syntax is a concise and convenient feature that allows us to build a dictionary from elements of another iterables in less lines of code.
  • The most basic syntax of dictionary comprehension is {key: value for vars in iterable}
  • We can  use if conditions in the comprehension to filter elements of the iterable.
  • We can use multiple for statements in the comprehension to achieve nested for loops.
  • We should generally avoid making a comprehension too complex to avoid debugging and readability issues.