Back to Blog
Python

Python dict fromkeys: Usage, Pitfalls, and Alternatives

python dict fromkeys: Learn how dict.fromkeys works, the shared mutable value pitfall, and when to use it instead of a dict comprehension.

pythondictionaryfromkeysdata-structurespython-tips
A Python dictionary being created from a list of keys with a single shared value, illustrating the fromkeys method.

The dict.fromkeys method creates a new dictionary from a sequence of keys and a single value. It is a concise way to initialize a dictionary when all keys should share the same initial value. However, its behavior with mutable defaults often surprises developers. This article explains how python dict fromkeys works, where it fails, and when to use an alternative.

How dict.fromkeys Works

The method is a class method on dict, so you call it as dict.fromkeys(iterable, value). It returns a new dictionary where each element of the iterable becomes a key, and every key maps to the same value. If you omit the value, it defaults to None.

keys = ['a', 'b', 'c'] d = dict.fromkeys(keys) print(d) # {'a': None, 'b': None, 'c': None} d_with_value = dict.fromkeys(keys, 0) print(d_with_value) # {'a': 0, 'b': 0, 'c': 0}

The iterable can be any sequence, such as a list, tuple, or string. The keys are inserted in the order they appear in the iterable, which matters for Python 3.7+ where dictionary order is guaranteed.

The Shared-Value Pitfall

When the value passed to fromkeys is a mutable object—like a list, dict, or set—all keys reference the same object. Mutating that object through one key affects every key. This is a common source of bugs.

d = dict.fromkeys(['x', 'y'], []) d['x'].append(1) print(d) # {'x': [1], 'y': [1]}

To give each key its own independent mutable value, you must use a dictionary comprehension or an explicit loop. For example:

keys = ['x', 'y'] d = {k: [] for k in keys} d['x'].append(1) print(d) # {'x': [1], 'y': []}

The comprehension evaluates the value expression for each key, creating a fresh list each time. fromkeys evaluates its value argument once and reuses the same object.

Using fromkeys for Immutable Defaults

When the default value is immutable—such as an integer, string, tuple, or None—the shared reference is not a problem because immutable objects cannot be modified in place. This makes fromkeys a natural fit for initializing counters, flags, or lookup tables.

word_count = dict.fromkeys(words, 0) status = dict.fromkeys(user_ids, 'pending')

These patterns are readable and efficient. The method avoids an explicit loop and clearly communicates that all keys start with the same state.

Performance and Memory Considerations

fromkeys is implemented in C and is generally faster than a dictionary comprehension when the value is immutable. For large iterables, this speed difference can be noticeable, though the exact margin depends on the interpreter and the size of the data. The memory footprint is also smaller because the single value object is shared, which is safe only for immutable types.

If you need independent mutable values, a comprehension is the correct approach despite the extra allocation cost. The performance difference is rarely the deciding factor; correctness is.

ApproachValue behaviorUse case
dict.fromkeys(keys, value)Shared referenceImmutable defaults
{k: value for k in keys}Fresh expression per keyMutable defaults
{k: [] for k in keys}Independent list per keyMutable defaults with list

Common Mistakes and Edge Cases

One mistake is assuming fromkeys copies the value for each key. It does not. Another is passing a list as the value and then appending to it, expecting each key to have its own list. As shown earlier, that leads to shared state.

Another edge case involves using a set or a generator as the iterable. Sets do not guarantee order, so the resulting dictionary order may vary. Generators work, but they are consumed once—reusing the same generator for multiple fromkeys calls will not produce the same result.

keys = ['a', 'b'] d1 = dict.fromkeys(keys, []) d2 = dict.fromkeys(keys, []) print(d1 is d2) # False, but the value lists are shared within each dict

Also note that fromkeys does not accept keyword arguments for the value; it only takes two positional parameters.

When Not to Use fromkeys

Avoid fromkeys when you need each key to map to a distinct mutable object. In that case, a dictionary comprehension or a loop with explicit assignment is clearer and safer.

Avoid it when the default value depends on the key. For example, if you want to initialize a dictionary where each key maps to a list that already contains the key itself, you need a comprehension:

keys = ['a', 'b'] d = {k: [k] for k in keys} print(d) # {'a': ['a'], 'b': ['b']}

Similarly, if the value must be computed from the key or from external data, fromkeys is not suitable because it accepts a single static value.

For simple immutable defaults, fromkeys is a compact and idiomatic choice. For anything more complex, prefer an explicit construction method. Understanding this boundary prevents subtle bugs and keeps code maintainable.

python dict fromkeys: Practical Usage and Code Examples | RYUSLOG DEV