Chapters
Python114 chapters

CollectionsChapter 41 of 114

Dict and Set Comprehensions

Build a dictionary or a set in one line, the same way you build a list.

The shape

Same as a list comprehension, with different brackets. A dictionary needs a key: value pair:

Python
words = ["ada", "grace", "kat"]

print({word: len(word) for word in words})
print({len(word) for word in words})

Output

{'ada': 3, 'grace': 5, 'kat': 3}
{3, 5}

The set dropped the duplicate 3, because that is what sets do.

Filtering

Python
scores = {"ada": 9, "grace": 4, "kat": 7}

print({name: score for name, score in scores.items() if score > 5})

Output

{'ada': 9, 'kat': 7}

Reading through .items() and building a new dictionary is the idiomatic way to filter one. There is no dict.filter.

Transforming

Python
prices = {"book": 10, "pen": 2}

print({item: price * 1.2 for item, price in prices.items()})
print({item.upper(): price for item, price in prices.items()})

Output

{'book': 12.0, 'pen': 2.4}
{'BOOK': 10, 'PEN': 2}

Inverting a dictionary

Swapping keys and values is a one-liner:

Python
codes = {"uk": 44, "de": 49}
print({number: country for country, number in codes.items()})

Output

{44: 'uk', 49: 'de'}
Python
scores = {"ada": 9, "grace": 9}
print({score: name for name, score in scores.items()})

Output

{9: 'grace'}

Two names went in and one came out. When values repeat, group into lists instead:

Python
scores = {"ada": 9, "grace": 9, "kat": 7}
grouped = {}
for name, score in scores.items():
    grouped.setdefault(score, []).append(name)
print(grouped)

Output

{9: ['ada', 'grace'], 7: ['kat']}

Building from two lists

Python
names = ["ada", "grace"]
years = [1815, 1906]

print({name: year for name, year in zip(names, years)})
print(dict(zip(names, years)))

Output

{'ada': 1815, 'grace': 1906}
{'ada': 1815, 'grace': 1906}

When there is no transforming to do, dict(zip(...)) says it more directly.

Set comprehensions

Python
words = ["Ada", "ada", "GRACE"]

print(sorted({word.lower() for word in words}))
print(sorted({len(w) for w in words if w.isupper()}))

Output

['ada', 'grace']
[5]

Sort before printing a set. The display order is not stable between runs.

There is no tuple comprehension

Round brackets give a generator, not a tuple:

Python
squares = (n * n for n in range(4))
print(type(squares).__name__)
print(tuple(n * n for n in range(4)))

Output

generator
(0, 1, 4, 9)

Wrap it in tuple() when you want one.

Test yourself

2 questions

What happens when you invert a dictionary whose values repeat?

Show the answer

Entries collapse, and the last one wins — Group into lists with setdefault when the values are not unique.

What does (n for n in items) build?

Show the answer

A generator — There is no tuple comprehension. Wrap it in tuple() when you want one.

Next chapter

The collections Module

Counter, defaultdict, deque and namedtuple, and when each is the right tool.