Python
dictionary initialization
programming
keys list
coding tutorial

How to initialize a dict with keys from a list and empty value in Python?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Creating a dictionary from a list of keys with a default value is one of the most common dictionary operations in Python. Whether you are initializing counters, building lookup tables, or preparing data structures for later population, knowing the right approach matters. This article covers the main techniques, explains a critical trap that catches even experienced developers, and shows you when to use each method.

Using dict.fromkeys()

The built-in dict.fromkeys() class method is the most concise way to create a dictionary from a list of keys, all set to the same default value.

python
1keys = ["name", "age", "email"]
2
3# All values set to None
4d = dict.fromkeys(keys)
5print(d)
6# {'name': None, 'age': None, 'email': None}
7
8# All values set to a specific default
9d = dict.fromkeys(keys, 0)
10print(d)
11# {'name': 0, 'age': 0, 'email': 0}
12
13# Works with any iterable, not just lists
14d = dict.fromkeys(range(5), "default")
15print(d)
16# {0: 'default', 1: 'default', 2: 'default', 3: 'default', 4: 'default'}

This method is clean, readable, and runs in O(n) time where n is the number of keys. However, it has a dangerous trap when used with mutable defaults.

The Mutable Default Trap

This is the single most important thing to understand about dict.fromkeys(). When you pass a mutable object like a list or dictionary as the default value, every key shares a reference to the same object. Modifying one modifies them all.

python
1keys = ["a", "b", "c"]
2
3# DANGER: all values point to the SAME list
4d = dict.fromkeys(keys, [])
5d["a"].append(1)
6print(d)
7# {'a': [1], 'b': [1], 'c': [1]}  <-- all three changed!
8
9# Verify they are the same object
10print(d["a"] is d["b"])
11# True

This happens because fromkeys() evaluates the default value once and assigns that single reference to every key. It does not create a new list for each key. If you need mutable defaults, use a dictionary comprehension instead.

Using Dictionary Comprehension

A dictionary comprehension creates a fresh value for each key, which makes it the safe choice when your default value is mutable.

python
1keys = ["a", "b", "c"]
2
3# Each key gets its OWN empty list
4d = {k: [] for k in keys}
5d["a"].append(1)
6print(d)
7# {'a': [1], 'b': [], 'c': []}  <-- only 'a' changed
8
9# Works with any expression
10d = {k: set() for k in keys}
11d = {k: {"count": 0} for k in keys}
12d = {k: k.upper() for k in keys}
13print(d)
14# {'a': 'A', 'b': 'B', 'c': 'C'}

The comprehension evaluates the value expression on each iteration, so every key gets an independent object. This is the method you should reach for by default whenever mutable values are involved.

Using collections.defaultdict

If you do not know all the keys upfront, or you want values to be created lazily on first access, defaultdict from the collections module is the right tool.

python
1from collections import defaultdict
2
3# Creates an empty list automatically when a missing key is accessed
4d = defaultdict(list)
5d["a"].append(1)
6d["b"].append(2)
7print(d)
8# defaultdict(<class 'list'>, {'a': [1], 'b': [2]})
9
10# Works with any callable
11d = defaultdict(int)      # defaults to 0
12d = defaultdict(set)      # defaults to empty set
13d = defaultdict(lambda: "unknown")  # defaults to "unknown"

The key advantage of defaultdict is that you never need to check whether a key exists before using it. The factory function is called automatically for missing keys, which simplifies code that accumulates values.

Comparing the Approaches

Here is a practical comparison to help you choose.

python
1keys = ["x", "y", "z"]
2
3# Immutable default (all three work correctly)
4d1 = dict.fromkeys(keys, 0)
5d2 = {k: 0 for k in keys}
6
7# Mutable default (only comprehension and defaultdict are safe)
8d3 = {k: [] for k in keys}           # safe
9d4 = dict.fromkeys(keys, [])         # UNSAFE - shared reference
10
11# Unknown keys at creation time (defaultdict wins)
12from collections import defaultdict
13d5 = defaultdict(list)
14d5["new_key"].append("value")        # no KeyError

Use dict.fromkeys() for immutable defaults when you want clean, readable code. Use dictionary comprehensions when the default value is mutable. Use defaultdict when keys are discovered dynamically during program execution.

Common Pitfalls

  • Using dict.fromkeys() with a mutable default causes all keys to share the same object. Always use a comprehension for lists, sets, or dicts as values.
  • Passing None to fromkeys and forgetting to handle it leads to TypeError later when you try to operate on the None values without checking first.
  • Using defaultdict when you need KeyError behavior silently creates entries for typos and missing keys. Use a regular dict if you want access to non-existent keys to fail loudly.
  • Forgetting that dict.fromkeys() deduplicates keys means if your list contains duplicates, the resulting dictionary will have fewer entries than expected, since dictionaries cannot have duplicate keys.
  • Confusing {}.fromkeys() with dict.fromkeys() produces the same result, but dict.fromkeys() is more readable and conventional. Calling it on an instance is misleading because the instance's existing contents are ignored.

Summary

  • dict.fromkeys(keys, default) is the fastest one-liner for immutable defaults like 0, "", None, or False.
  • Dictionary comprehensions ({k: value for k in keys}) create independent value objects per key, making them safe for mutable defaults.
  • defaultdict(factory) lazily creates values on first access, ideal when you do not know all keys ahead of time.
  • Never use dict.fromkeys() with a mutable default value. This is the most common source of bugs with this pattern.
  • Choose the method based on whether your default is mutable and whether your keys are known at creation time.

Course illustration
Course illustration

All Rights Reserved.