Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python SyntaxError with dict(1=...), but {1:...} works

Python seems to have an inconsistency in what kind of keys it will accept for dicts. Or, put another way, it allows certain kinds of keys in one way of defining dicts, but not in others:

>>> d = {1:"one",2:2}
>>> d[1]
'one'
>>> e = dict(1="one",2=2)
  File "<stdin>", line 1
  SyntaxError: keyword can't be an expression

Is the {...} notation more fundamental, and dict(...) just syntactic sugar? Is it because there is simply no way for Python to parse dict(1="one")?

I'm curious...

like image 918
abalter Avatar asked Apr 30 '12 21:04

abalter


4 Answers

This is not a dict issue, but an artifact of Python syntax: keyword arguments must be valid identifiers, and 1 and 2 are not.

When you want to use anything that is not a string following Python identifier rules as a key, use the {} syntax. The constructor keyword argument syntax is just there for convenience in some special cases.

like image 64
Fred Foo Avatar answered Nov 01 '22 03:11

Fred Foo


dict is a function call, and function keywords must be identifiers.

like image 44
Mark Ransom Avatar answered Nov 01 '22 03:11

Mark Ransom


As other answer have stated, dict is a function call. It has three syntactic forms.

The form:

dict(**kwargs) -> new dictionary initialized with the name=value pairs
   in the keyword argument list.  For example:  dict(one=1, two=2)

The keys (or name as used in this case) must be valid Python identifiers, and ints are not valid.

The limitation is not only the function dict You can demonstrate it like so:

>>> def f(**kw): pass
... 
>>> f(one=1)    # this is OK
>>> f(1=one)    # this is not
  File "<stdin>", line 1
SyntaxError: keyword can't be an expression

However, there are two other syntactic forms of you can use.

There is:

dict(iterable) -> new dictionary initialized as if via:
       d = {}
       for k, v in iterable:
           d[k] = v

Example:

>>> dict([(1,'one'),(2,2)])
{1: 'one', 2: 2}

And from a mapping:

dict(mapping) -> new dictionary initialized from a mapping object's
   (key, value) pairs

Example:

>>> dict({1:'one',2:2})
{1: 'one', 2: 2}

While that may not seem like much (a dict from a dict literal) keep in mind that Counter and defaultdict are mappings and this is how you would covert one of those to a dict:

>>> from collections import Counter
>>> Counter('aaaaabbbcdeffff')
Counter({'a': 5, 'f': 4, 'b': 3, 'c': 1, 'e': 1, 'd': 1})
>>> dict(Counter('aaaaabbbcdeffff'))
{'a': 5, 'c': 1, 'b': 3, 'e': 1, 'd': 1, 'f': 4}
like image 38
dawg Avatar answered Nov 01 '22 01:11

dawg


If you read the documentation, you will learn that the dict = {stringA = 1, stringB = 2} notation is valid when the keys are simple strings:

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}

Since integers (or other numbers) are not valid keyword arguments, the dict = {1 = 2, 3 = 4} will fail as any call to a function would if you passed an argument to it while naming it with a number:

>>> def test(**kwargs):
...     for arg in kwargs:
...         print arg, kwargs[arg]
... 
>>> test(a=2,b=3)
a 2
b 3
>>> test(1=2, 3=4)
  File "<stdin>", line 1
SyntaxError: keyword can't be an expression
like image 27
berna1111 Avatar answered Nov 01 '22 01:11

berna1111