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:
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
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
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:
codes = {"uk": 44, "de": 49}
print({number: country for country, number in codes.items()})Output
{44: 'uk', 49: 'de'}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:
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
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
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:
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 questionsWhat 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.
The collections Module
Counter, defaultdict, deque and namedtuple, and when each is the right tool.