What's the difference between dict() and {}?
Solution 1:
>>> def f():
... return {'a' : 1, 'b' : 2}
...
>>> def g():
... return dict(a=1, b=2)
...
>>> g()
{'a': 1, 'b': 2}
>>> f()
{'a': 1, 'b': 2}
>>> import dis
>>> dis.dis(f)
2 0 BUILD_MAP 0
3 DUP_TOP
4 LOAD_CONST 1 ('a')
7 LOAD_CONST 2 (1)
10 ROT_THREE
11 STORE_SUBSCR
12 DUP_TOP
13 LOAD_CONST 3 ('b')
16 LOAD_CONST 4 (2)
19 ROT_THREE
20 STORE_SUBSCR
21 RETURN_VALUE
>>> dis.dis(g)
2 0 LOAD_GLOBAL 0 (dict)
3 LOAD_CONST 1 ('a')
6 LOAD_CONST 2 (1)
9 LOAD_CONST 3 ('b')
12 LOAD_CONST 4 (2)
15 CALL_FUNCTION 512
18 RETURN_VALUE
dict() is apparently some C built-in. A really smart or dedicated person (not me) could look at the interpreter source and tell you more. I just wanted to show off dis.dis. :)
Solution 2:
As far as performance goes:
>>> from timeit import timeit
>>> timeit("a = {'a': 1, 'b': 2}")
0.424...
>>> timeit("a = dict(a = 1, b = 2)")
0.889...
Solution 3:
@Jacob: There is a difference in how the objects are allocated, but they are not copy-on-write. Python allocates a fixed-size "free list" where it can quickly allocate dictionary objects (until it fills). Dictionaries allocated via the {}
syntax (or a C call to PyDict_New
) can come from this free list. When the dictionary is no longer referenced it gets returned to the free list and that memory block can be reused (though the fields are reset first).
This first dictionary gets immediately returned to the free list, and the next will reuse its memory space:
>>> id({})
340160
>>> id({1: 2})
340160
If you keep a reference, the next dictionary will come from the next free slot:
>>> x = {}
>>> id(x)
340160
>>> id({})
340016
But we can delete the reference to that dictionary and free its slot again:
>>> del x
>>> id({})
340160
Since the {}
syntax is handled in byte-code it can use this optimization mentioned above. On the other hand dict()
is handled like a regular class constructor and Python uses the generic memory allocator, which does not follow an easily predictable pattern like the free list above.
Also, looking at compile.c from Python 2.6, with the {}
syntax it seems to pre-size the hashtable based on the number of items it's storing which is known at parse time.