Reputation: 33
I got two strings retrieved from a cookie
name = 'rack.session'
val = 'CookieVal'
Using them I would like to build a dictionary
cookies = dict(rack.session=val)
but SyntaxError: keyword can't be an expression
So I tried to escape the (.) dot
re.escape(name)
... but it raises the same error
How is this possible? According to Python type()
name is a string:
type(name)
<class 'str'>
Why is Python mixing up strings and expressions?
Upvotes: 3
Views: 13404
Reputation: 151
The answer from Ashwini Chaudhary was quite good, but I can add more to clarify question.
The main reason why you've got this error is because your expression contain a point - '.' symbol. And raising error directly say that: "keyword can't be an expression".
This - '.' symbol makes Python think, that current keyword name is not a valid name, but an expression, that you try to evaluate. Generally speaking you may pass as a key in dict() only valid name, from the point that such names could be a names for a variables dispite the fact that no variable evaluation actually can be happen here.
So your keys must contain only alphabeticals, digits, or underscore, and do not start with a digit (they must be valid Python identifiers as was said before).
For example these are not valid:
d = dict(1='Bob')
d = dict(b.a='Bob')
d = dict('b'='Bob')
d = dict(b$='Bob')
First, second and third are not valid, because they are expressions and because they are not valid identifiers, but fourth only because it is not a valid identifier.
To circumvent current limitations you may use one of the ways that was mentioned above, cause they accepting variable evaluation and if the key is the string, it can contain any characters:
d = dict([(1, 'Bob')])
d = dict(zip([1],['Bob']))
d = {1:'bob'}
or this one:
d = dict.fromkeys([1])
d[1] = 'Bob'
And for example of key value evaluation difference:
x = 1
d = dict(x='Bob')
d
{'x': 'Bob'}
x = 1
d = dict([(x, 'Bob')])
d
{1: 'Bob'}
Upvotes: 0
Reputation: 251116
The problem with rack.session
is that python thinks that you're trying to use the value of expression rack.session
and pass it to dict()
, which is incorrect because dict()
expects you to pass variables names when you're using keyword arguments, these variables name are then converted to strings when the dict is created.
Simple example:
>>> dict('val' = 'a')
File "<ipython-input-21-1cdf9688c191>", line 1
SyntaxError: keyword can't be an expression
So, you can't use an object on the left side of =
, you can only use a valid identifier.
Byte code makes it even more clear what happens with rack.session
:
>>> import dis
>>> dis.dis(lambda : dict(rack.session , val))
1 0 LOAD_GLOBAL 0 (dict)
3 LOAD_GLOBAL 1 (rack) # load the object `rack`
6 LOAD_ATTR 2 (session)# use the value of it's attribute
# `session`
9 LOAD_GLOBAL 3 (val)
12 CALL_FUNCTION 2
15 RETURN_VALUE
So, with rack.session = val
, python will think that you're trying to use the value returned from rack.session
and pass it to dict
, which is incorrect. Secondly rack.session
isn't a valid identifier as dots(.
) are not allowed in python identifiers.
This is applicable to any function in python not even dict
, a keyword argument must be a valid identifier.
From the docs:
keyword_item ::= identifier "=" expression
Valid examples:
>>> dict(foo = 1, bar = '2')
{'foo': 1, 'bar': '2'}
For your example you can simply do:
>>> val = 'CookieVal'
>>> name = 'rack.session'
>>> dict(((name,val),))
{'rack.session': 'CookieVal'}
#or
>>> {name:val}
{'rack.session': 'CookieVal'}
Upvotes: 9
Reputation: 26333
You should build a dictionary this way
name = 'rack.session'
val = 'CookieVal'
d = {name: val}
print d
gives you
>>>
{'rack.session': 'CookieVal'}
>>>
More on dictionaries http://docs.python.org/2/tutorial/datastructures.html#dictionaries
Upvotes: 1
Reputation: 27812
The reason is that you give the dict
this expression: rack.session=val
, rather than a keyword.
Instead, you can get around this issue using dict({name: val})
, where the argument is {name:val}
. Of course, you could just use {name: val}
.
The python docs shows several ways to create dicts.
Upvotes: 0
Reputation: 49866
name = 'rack.session'
val = 'CookieVal'
cookies = dict([(name,val)])
morecookies = {name:val}
As to "Why is Python mixing up strings and expressions?", it's not. I'm not sure why you think python is doing this. You are mixing up strings and variables, which are quite different.
Upvotes: 1
Reputation: 3775
Try this:
name = 'rack.session'
val = 'CookieVal'
cookies = dict(zip([name],[val]))
Edit: my case is too much for your case
cookies = {name:val}
is enough
Upvotes: -1
Reputation: 474131
>>> name = 'rack.session'
>>> val = 'CookieVal'
>>> cookies = {name: val}
>>> cookies
{'rack.session': 'CookieVal'}
Upvotes: 1