views:

237

answers:

6

In some Python code I've read I keep noticing this code:

return dict(somekey=somevalue)

Does that have any benefit over:

return {somekey:somevalue}

I tend to say no, since both objects will belong to the same dict type, but I may be wrong.

+5  A: 

They are semantically identical.

The dict( param=value, ... ) notation limits your keys to strings which are valid python identifiers.

The dict( sequence-of-2-tuples ) is effectively the same as {}.

The {} notation places no limits on the keys. Except that they be hashable objects.

There are performance differences.

S.Lott
`dict` has a feature I have seen on this site, but I don't find it intuitive myself; you can concatenate two dicts in one statement with: `D = dict(d1, **d2)`. It is neat but a bit broken since `d2` must have string keys only.
kaizer.se
I believe `d3 = dict(d1); d3.update(d2)` is the more common, Pythonic, and safer method for merging two dictionaries.
ephemient
+1  A: 

The curly braces are a syntaxtic nicity, so the only benefit is can more clearly express the structure of the dict.

Mark Roddy
+1  A: 

dict(somekey=somevalue) is exactly the same as {'somekey': somevalue}. (Your two examples, then, aren't quite quivalent—in the first case the key is the string 'somekey' as the key and in the second it is whatever somekey is.) It is generally nicer just to use dict literals unless you are avoiding typing all the quotes.

Mike Graham
+13  A: 
>>> def foo(): return dict(a=1)
...
>>> def bar(): return {'a':1}
...
>>> import dis
>>> dis.dis(foo)
  1           0 LOAD_GLOBAL              0 (dict)
              3 LOAD_CONST               1 ('a')
              6 LOAD_CONST               2 (1)
              9 CALL_FUNCTION          256
             12 RETURN_VALUE
>>> dis.dis(bar)
  1           0 BUILD_MAP                1
              3 LOAD_CONST               1 (1)
              6 LOAD_CONST               2 ('a')
              9 STORE_MAP
             10 RETURN_VALUE
>>> import timeit
>>> timeit.Timer(foo).timeit()
0.76093816757202148
>>> timeit.Timer(bar).timeit()
0.31897807121276855

There is no functional difference, but the latter is more efficient.

ephemient
+2  A: 

{somekey:somevalue} can only be used as a literal, it doesn't allow any looping inside the brackets.

dict takes **kwargs, which means you can for example do dict( **locals() ). dict(somekey=somevalue) is just a nice shortcut when you don't want to type quotes and braces.

There is a third dict constructor too, dict([(key,val),(key2,val2)]). Its the most powerful and often used with zip

THC4k
BTW, Python 3 generalizes list comprehensions to allow dict (and set) comprehensions as well: i.e. {k:v for k, v in stuff if expr}
Ned Deily
+2  A: 

Python is dynamic -- so you can redefine what 'dict' means in any of your scopes, while Python's syntax is absolutely nonprogrammable. Thus the Python parser can conclude, when it sees the curly braces, that it must build a dict. A dict(..) expression must always be evaluated like any other function call; lookup the name, build argument tuple etc.

In effect, using container literals like the {} curly braces is the closest you can come to static type declarations in Python.

I think this has influenced the Python 3 decision to introduce set literals like s = {1,2,3}.


It does happen that programmers reassign python builtins! I think this is mostly by mistake, and mostly limited to local variables (and Python's namespaces make sure it can't do too much harm!) Here is a Google Code Search for code reassigning dict. I think the strangest example is dict = dict(); by that point, it should be obvious what you are doing!

That it's possible to do this doesn't mean you should do it. Yes, for example thinking that dict should really be called hash in python and swapping out the other builtin called hash is not something you should do:

hash, checksum = dict, hash

:-)

An example of code that does this is found right in the Python standard library. That's right, here is from line 92 of shelve.py:

def __init__(self, dict, protocol=None, writeback=False):
    self.dict = dict
    if protocol is None:
        protocol = 0
    self._protocol = protocol
    self.writeback = writeback
    self.cache = {}

This is a very typical example; dict is used as a method argument, and no-one notices and it does no harm, since the method is very short. Use syntax highlighting for builtins to catch this, is my suggestion.

kaizer.se
+1 for bringing up Python's dynamicism as a justification. On the other hand, while it's legal, you'd be fairly crazy to redefine `dict` -- it'll break Psyco, not to mention confusing everybody else working with your code.
ephemient