Using PyCharm, I noticed it offers to convert a dict literal:
d = {
'one': '1',
'two': '2',
}
into a dict constructor:
d = dict(one='1', two='2')
Do these different approaches differ in some significant way?
(While writing this question I noticed that using dict()
it seems impossible to specify a numeric key .. d = {1: 'one', 2: 'two'}
is possible, but, obviously, dict(1='one' ...)
is not. Anything else?)
This question is related to
python
dictionary
pycharm
I find the dict literal d = {'one': '1'}
to be much more readable, your defining data, rather than assigning things values and sending them to the dict()
constructor.
On the other hand i have seen people mistype the dict literal as d = {'one', '1'}
which in modern python 2.7+ will create a set.
Despite this i still prefer to all-ways use the set literal because i think its more readable, personal preference i suppose.
There is no dict literal to create dict-inherited classes, custom dict classes with additional methods. In such case custom dict class constructor should be used, for example:
class NestedDict(dict):
# ... skipped
state_type_map = NestedDict(**{
'owns': 'Another',
'uses': 'Another',
})
These two approaches produce identical dictionaries, except, as you've noted, where the lexical rules of Python interfere.
Dictionary literals are a little more obviously dictionaries, and you can create any kind of key, but you need to quote the key names. On the other hand, you can use variables for keys if you need to for some reason:
a = "hello"
d = {
a: 'hi'
}
The dict()
constructor gives you more flexibility because of the variety of forms of input it takes. For example, you can provide it with an iterator of pairs, and it will treat them as key/value pairs.
I have no idea why PyCharm would offer to convert one form to the other.
Also consider the fact that tokens that match for operators can't be used in the constructor syntax, i.e. dasherized keys.
>>> dict(foo-bar=1)
File "<stdin>", line 1
SyntaxError: keyword can't be an expression
>>> {'foo-bar': 1}
{'foo-bar': 1}
the dict() literal is nice when you are copy pasting values from something else (none python) For example a list of environment variables. if you had a bash file, say
FOO='bar'
CABBAGE='good'
you can easily paste then into a dict()
literal and add comments. It also makes it easier to do the opposite, copy into something else. Whereas the {'FOO': 'bar'}
syntax is pretty unique to python and json. So if you use json a lot, you might want to use {}
literals with double quotes.
From python 2.7 tutorial:
A pair of braces creates an empty dictionary: {}. Placing a comma-separated list of key:value pairs within the braces adds initial key:value pairs to the dictionary; this is also the way dictionaries are written on output.
tel = {'jack': 4098, 'sape': 4139}
data = {k:v for k,v in zip(xrange(10), xrange(10,20))}
While:
The dict() constructor builds dictionaries directly from lists of key-value pairs stored as tuples. When the pairs form a pattern, list comprehensions can compactly specify the key-value list.
tel = dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) {'sape': 4139, 'jack': 4098, 'guido': 4127}
data = dict((k,v) for k,v in zip(xrange(10), xrange(10,20)))
When the keys are simple strings, it is sometimes easier to specify pairs using keyword arguments:
dict(sape=4139, guido=4127, jack=4098)
>>> {'sape': 4139, 'jack':4098, 'guido': 4127}
So both {} and dict() produce dictionary but provide a bit different ways of dictionary data initialization.
One big difference with python 3.4 + pycharm is that the dict() constructor produces a "syntax error" message if the number of keys exceeds 256.
I prefer using the dict literal now.
They look pretty much the same on Python 3.2.
As gnibbler pointed out, the first doesn't need to lookup dict
, which should make it a tiny bit faster.
>>> def literal():
... d = {'one': 1, 'two': 2}
...
>>> def constructor():
... d = dict(one='1', two='2')
...
>>> import dis
>>> dis.dis(literal)
2 0 BUILD_MAP 2
3 LOAD_CONST 1 (1)
6 LOAD_CONST 2 ('one')
9 STORE_MAP
10 LOAD_CONST 3 (2)
13 LOAD_CONST 4 ('two')
16 STORE_MAP
17 STORE_FAST 0 (d)
20 LOAD_CONST 0 (None)
23 RETURN_VALUE
>>> dis.dis(constructor)
2 0 LOAD_GLOBAL 0 (dict)
3 LOAD_CONST 1 ('one')
6 LOAD_CONST 2 ('1')
9 LOAD_CONST 3 ('two')
12 LOAD_CONST 4 ('2')
15 CALL_FUNCTION 512
18 STORE_FAST 0 (d)
21 LOAD_CONST 0 (None)
24 RETURN_VALUE
Literal is much faster, since it uses optimized BUILD_MAP and STORE_MAP opcodes rather than generic CALL_FUNCTION:
> python2.7 -m timeit "d = dict(a=1, b=2, c=3, d=4, e=5)"
1000000 loops, best of 3: 0.958 usec per loop
> python2.7 -m timeit "d = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5}"
1000000 loops, best of 3: 0.479 usec per loop
> python3.2 -m timeit "d = dict(a=1, b=2, c=3, d=4, e=5)"
1000000 loops, best of 3: 0.975 usec per loop
> python3.2 -m timeit "d = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5}"
1000000 loops, best of 3: 0.409 usec per loop
Source: Stackoverflow.com