dict()

Three constructors wearing one name. Which form you use decides what your keys are allowed to be.

Built-in function / typePython 1.0+Live demo
Common call
dict(mapping)
Returns
a new dict — a shallow copy when the source is a mapping
Replaces
a manual loop assigning d[k] = v
Watch out
the keyword form only accepts valid identifiers as keys
dict(**kwargs) | dict(mapping) | dict(iterable)
dict

Demo

Live evaluation
Try:
Inputs
mappingmappingkey:value pairs, comma separated
Output
dict({'a': '1', 'b': '2'})
{'a': '1', 'b': '2'}

The demo shows the mapping form: dict(m) builds a new dict holding the same pairs. Insertion order is preserved — guaranteed since 3.7 — so the result reads back in the order the pairs went in. The copy is shallow, meaning the new dict is independent but the values inside it are the very same objects as before.

Parameters

NameTypeRequiredDescription
mappingmappingnoAn existing mapping to copy. The copy is shallow — the values are the same objects.
iterableiterablenoAn iterable of (key, value) pairs. Later pairs overwrite earlier ones with the same key.
kwargsAnynoKeyword arguments become string keys. Only valid Python identifiers are expressible this way.

Return value

dictA new dict. Built from a mapping, an iterable of key-value pairs, keyword arguments, or empty when given nothing.

Common patterns

Shallow-copy a dict
A new mapping you can mutate without touching the original.
config = dict(defaults)
Build from pairs
Anything yielding two-item pairs works, which makes zip a natural partner.
lookup = dict(zip(keys, values))
Merge with overrides
Later sources win. On 3.9+ the | operator says the same thing more briefly.
merged = dict(defaults, **overrides)
merged = defaults | overrides   # 3.9+

Examples

1. From a mapping
dict({'a': 1, 'b': 2})
Returns
{'a': 1, 'b': 2}
2. From pairs
dict([('a', 1), ('b', 2)])
Returns
{'a': 1, 'b': 2}
3. From keywords
dict(a=1, b=2)
Returns
{'a': 1, 'b': 2}
4. From zip
dict(zip('ab', [1, 2]))
Returns
{'a': 1, 'b': 2}
5. Empty
dict()
Returns
{}
6. Later pair wins
dict([('a', 1), ('a', 2)])
Returns
{'a': 2}

Pitfalls

1. The keyword form only takes identifiers
dict(a=1) is convenient right up to the point a key contains a space, a dash, or starts with a digit — then it is a syntax error rather than a runtime one.
Not valid syntax
dict(my-key=1)
SyntaxError: expression cannot contain assignment
Use a literal
{'my-key': 1}
{'my-key': 1}
2. The copy is shallow
dict(d) makes a new outer mapping whose values are the SAME objects. Mutating a nested list or dict shows through in both.
Shared inner
a = {'k': [1]}
b = dict(a)
b['k'].append(2)
a
{'k': [1, 2]}
Deep copy
import copy
b = copy.deepcopy(a)
fully independent
3. Duplicate keys silently collapse
Building from pairs, the last value for a key wins and the earlier ones vanish without warning. Easy to miss when the pairs come from data rather than a literal.
First lost
dict([('a', 1), ('a', 2)])
{'a': 2}
Group instead
from collections import defaultdict
d = defaultdict(list)
for k, v in pairs:
    d[k].append(v)
every value kept
4. Keys must be hashable
A list cannot be a key. This surfaces when keying by a composite value — convert it to a tuple first.
List key
dict([([1, 2], "v")])
TypeError: unhashable type: 'list'
Tuple key
dict([((1, 2), "v")])
{(1, 2): 'v'}

When to use

Use it
  • Shallow-copying an existing mapping
  • Building a lookup from parallel sequences via zip
  • Turning an iterable of pairs into a mapping
  • Merging defaults with overrides
Reach for something else
  • A fixed set of literal pairs → the {} literal is faster and clearer
  • Missing keys should get a default → collections.defaultdict
  • You need nested independence → copy.deepcopy

Notes

Complexity
O(n) — every pair is inserted into the new hash table
Return
Always a new dict; dict(d) copies rather than returning d
CPython impl
Objects/dictobject.c :: dict_init
Memory
A hash table sized for the input, with headroom to stay sparse
Thread-safe
The construction is safe; the resulting dict is not under concurrent mutation

FAQ

{} for a literal — it is faster, because it needs no global lookup and no function call. dict() earns its place when you are converting something, merging with keywords, or building from pairs.

empty = {}                    # preferred
lookup = dict(zip(ks, vs))    # conversion

History

1.0
dict has been a core built-in type since the earliest Python.
2.2
dict became a true type usable as a base class, rather than a factory function.
3.7
Insertion order became a language guarantee.
3.9
The | and |= merge operators added.