dict.fromkeys()

Class method — build a fresh dict from a set of keys, with every key pointing at the same default value.

Dict methodPython 2.3+Live demo
Common call
dict.fromkeys(keys, 0)
Returns
a new dict — all values are the SAME object
Replaces
`{k: default for k in keys}` when the default is immutable
Watch out
default is SHARED — dict.fromkeys(keys, []) gives every key the SAME list
dict.fromkeys(iterableiterableAny iterable of hashable keys. Duplicates collapse (last one wins, but they all get the same value).type: iterable · required, valuevalueThe default value for every key. Not copied — every key points at the exact same object.type: Any · default: None=None)
dict

Demo

Live evaluation
Try:
Inputs
keyslistcomma-separated keys
valueAnydefault value
Output
['a', 'b', 'c'].fromkeys('0')
{'a': '0', 'b': '0', 'c': '0'}

The demo shows the resulting dict. Duplicate keys in the input collapse (only one entry per key). The critical thing NOT visible in this demo — because we pass strings — is the shared-reference behavior: if you passed a mutable default like [] or {}, every key would point at THE SAME list or dict. See pitfalls.

Parameters

NameTypeRequiredDescription
iterableiterableyesAny iterable of hashable keys. Duplicates collapse (last one wins, but they all get the same value).
valueAnyno (None)The default value for every key. Not copied — every key points at the exact same object.

Return value

dictA NEW dict with keys from the iterable, all mapped to the SAME value. The value is not copied — every key shares the exact same object reference.

Common patterns

Initialize counters at zero
Immutable defaults like 0, "", and None are safe to share.
counts = dict.fromkeys(categories, 0)
Deduplicate while preserving order
Only the keys matter — the value is throwaway. Since 3.7 the key order is preserved.
unique = list(dict.fromkeys(items))   # order-preserving dedup
Set of allowed keys with None values
A skeleton dict that the caller will populate.
template = dict.fromkeys(fields)   # every field mapped to None

Examples

1. Basic
dict.fromkeys(["a", "b", "c"], 0)
Returns
{"a": 0, "b": 0, "c": 0}
2. Default value is None
dict.fromkeys(["x", "y"])
Returns
{"x": None, "y": None}
3. Order-preserving dedup
list(dict.fromkeys([3, 1, 2, 1]))
Returns
[3, 1, 2]
4. Duplicates collapse
dict.fromkeys("aabbcc")
Returns
{"a": None, "b": None, "c": None}
5. From a range
dict.fromkeys(range(3), "unset")
Returns
{0: "unset", 1: "unset", 2: "unset"}

Pitfalls

1. Mutable default is SHARED across all keys
The single most-copied footgun with fromkeys. The value is not copied — every key points at the SAME object. Appending to one key's list appears at every key.
Same list everywhere
d = dict.fromkeys(["a", "b"], [])
d["a"].append(1)
d
{"a": [1], "b": [1]} # both keys see the append
Comprehension makes copies
d = {k: [] for k in ["a", "b"]}
d["a"].append(1)
d
{"a": [1], "b": []}
2. It is a CLASS method, not an instance method
Called on the dict class, not on a dict instance. Calling on an instance works but reads awkwardly.
Confusing style
{"a": 1}.fromkeys(["x", "y"])   # ignores the receiver!
{"x": None, "y": None} # values NOT copied from the receiver
Class form
dict.fromkeys(["x", "y"])
{"x": None, "y": None}
3. Unhashable keys raise TypeError
Every key must be hashable. A list or dict in the iterable trips.
Unhashable
dict.fromkeys([[1, 2], [3, 4]])
TypeError: unhashable type: 'list'
Tuple keys
dict.fromkeys([(1, 2), (3, 4)])
{(1, 2): None, (3, 4): None}
4. The value is NOT type-checked against the keys
Any value type works — including a value that would be misleading given the domain. A common mistake is passing a callable, expecting each key to invoke it.
Same reference
d = dict.fromkeys(["a", "b"], list)
{"a": <class list>, "b": <class list>}
Comprehension calls it
d = {k: list() for k in ["a", "b"]}
{"a": [], "b": []} # separate lists

When to use

Use it
  • Initializing counters or flags with an immutable default (0, None, "")
  • Order-preserving deduplication of a list
  • Building a skeleton dict where the caller will populate values
  • Creating a &quot;set with values&quot; where every entry has the same tag
Reach for something else
  • Mutable default value → use a dict comprehension instead
  • Per-key computed defaults → dict comprehension or setdefault
  • Deep-copy semantics needed → comprehension with copy() or deepcopy()
  • Very large key iterables where a comprehension is more readable

Notes

Complexity
O(n) — one pass over the iterable
Return
A new dict; when called on a subclass, returns an instance of that subclass
CPython impl
Objects/dictobject.c :: dict_fromkeys_impl
Memory
One dict allocated; the value is stored by reference, not copied
Thread-safe
Yes — creation is a pure operation

FAQ

It builds a new dict from scratch — it does not need an existing dict to work with. Making it a classmethod keeps the API consistent: `dict.fromkeys(...)` reads like a factory call.

History

2.3
fromkeys() introduced as a class method on dict.
3.7
Insertion order preserved — enables the popular order-preserving dedup idiom.