How to turn a dictionary into attribute = value - python

I have the following dictionary in Python:
myDic = {}
myDic['username'] = 'smith44'
myDic['password'] = '123'
myDic['email'] = 'smith#gmail.com'
I want to turn this into:
username = 'smith44'
password = '123'
email = 'smith#gmail.com'
so that I can directly use username, password and email directly in one of my latter methods. I know I can use the dictionary but I need to do it this way for the sake of compatibility.
Again, what I need to do here is turn every dictionary key into a seperate attribute that will take the value of its corresponding dictionary value.
UPDATE
To further support what I need to do, here is what I've done so far:
for key, value in myDic.iteritems():
exec("%s = " "'""%s""'" % (key, value))

If you really really need to do this:
>>> d = {}
>>> d['test'] = "foo"
>>> locals().update(d)
>>> test
'foo'
But if I were you, I'd try to find a different way of solving the problem you're trying to solve instead of automatically adding variables to your local namespace. There's almost always a way around this mess.

you will get string in attribute = value format using str.join
In [12]: ", ".join(["%s = %s" % (k, v) for k,v in myDic.items()])
Out[12]: 'username = smith44, password = 123, email = smith#gmail.com'
In [13]: myDic.items()
Out[13]: [('username', 'smith44'), ('password', '123'), ('email', 'smith#gmail.com')]

Related

Python 2.7.8: Printing a sub-dictionary value?

I'm using ConfigParser which returns a dictionary of configuration data as such:
{'general': {'UserKey': 'thisisatestkey'}}
If I want to simply print the value of the UserKey key (in this case thisisatestkey), then I generally just do a print "Your key is: {0}".format(mydictvar.get('UserKey')).
If I just print out the raw dict to a string I get the above. If I use the print statement above I get result of None since there is no key in the root of the dict called UserKey. If I .get('general') I just get: {'UserKey': 'thisisatestkey'}
Obviously I could do a fore loop like so:
keydic = cp.get_config_data()
for m, k in keydic.iteritems():
for s, v in k.iteritems():
userkey = v
and then print userkey which works fine. But I want to know how I can just avoid having to do the entire for loop first and just print the darned value right inline? Thanks!
You can use
mydictvar['general']['UserKey']
Or, if keys might be missing
mydictvar.get('general', {}).get('UserKey')
mydictvar['general'] returns a dictionary object; you can then just apply [...] to that value to retrieve the next key.
This works in string formatting too:
>>> mydictvar = {'general': {'UserKey': 'thisisatestkey'}}
>>> print "Your key is: {0[general][UserKey]}".format(mydictvar)
Your key is: thisisatestkey
simply without loop:
>>> my_dict = {'general': {'UserKey': 'thisisatestkey'}}
>>> my_dict['general']['UserKey']
'thisisatestkey'

Python string to other classes

I have an 3rd party python method (ANSA) that returns strings based on user gui input with default values to start with.
The default values may look like this and are stored in a dictionary:
Label Value
Userdata1 123
Userdata2 'abc'
Userdata3 123.456
... ...
Now, these are all returned as a dictionary with string values by the 3rd party "back_box" function.
Is it, based on the class of the default values, possible to change the new string class back to the default classes?
Here is something that may make it a bit clearer:
data = {'Userdata1':123,
'Userdata2':'abc',
'Userdata3':123.456}
new_data = black_box(data) # Outputs dictionary with the values as strings
for i, var_name in enumerate(data):
original_class = type(data[var_name])
new_data[var_name] = new_data[var_name].StrToClass(original_class)
So what i am looking for is a method/function/magic trick called strToClass in the above example.
I know it may be a risky way to do it, but any ideas about pythonic ways to do it?
(python3 btw)
Just keep the types of the original values of the dictionary in a separate new dictionary, then use that dictionary to transform them back --
>>> my_dict = {'Userdata1':123,
'Userdata2':'abc',
'Userdata3':123.456}
>>> type_dict = {k:type(v) for k,v in my_dict.iteritems()}
>>> type_dict
{'Userdata2': <type 'str'>, 'Userdata3': <type 'float'>, 'Userdata1': <type 'int'>}
>>> str_dict = {k:str(v) for k,v in my_dict.iteritems()}
>>> str_dict
{'Userdata2': 'abc', 'Userdata3': '123.456', 'Userdata1': '123'}
>>> new_dict = {k:type_dict[k](v) for k,v in str_dict.iteritems()}
>>> new_dict
{'Userdata2': 'abc', 'Userdata3': 123.456, 'Userdata1': 123}
Or, using your pseudocode
for i, var_name in enumerate(data):
original_class = type(data[var_name])
new_data[var_name] = original_class(new_data[var_name])
I believe the magic function you're looking for is ast.literal_eval.
for i, var_name in enumerate(data):
new_data[var_name] = ast.literal_eval(new_data[var_name])
Never name a variable def
For complicated classes you'll need more work, however this should do nicely for basic types, and types that have a representation identical to other basic types
d = {'Userdata1':123,
'Userdata2':'abc',
'Userdata3':123.456}
# create a list containing each type
var_type = [ type(d[key]) for key in sorted(d.keys())]
d = black_box(d)
import ast
for vt, key in zip(var_type, sorted(d.keys())):
# if the variable was a string you're already done
if not vt == str:
# cast from string to generic type
d[key] = ast.literal_eval(d[key])
# cast from generic to original type
try:
d[key] = vt(d[key])
except:
print "Error converting dictionary value with key: " + key
print "Unable to cast {} as {}".format(d[key], vt)

Variables as hash values in Python

How can I link a variable to a dictionary value in Python?
Consider the following code:
a_var = 10
a_dict = {'varfield':a_var, 'first':25, 'second':57}
# a_dict['varfield'] == 10 now
a_var = 700
# a_dict['varfield'] == 10 anyway
So is there a way to link the value of a variable to a field in a dictictionary without looking up for that field an updating it's value manually?
You would need to set the value of the dictionary key, to an object that you can change the value of.
For example like this:
class valueContainer(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return self.value.__repr__()
v1 = valueContainer(1)
myDict = {'myvar': v1}
print myDict
#{'myvar': 1}
v1.value = 2
print myDict
#{'myvar': 2}
w = [410]
myDict = {'myvar': w}
print myDict
#{'myvar': [410]}
w[0] = 520
print myDict
#{'myvar': [520]}
That's the version of the code of M4rtini with a list instead of an instance of a class.
He is obliged to modify v1 (in fact its attribute value) with the instruction v1.value = ...,
I am obliged to modify the value in the list with w[0] = ...
The reason to act like this is that what you erroneously called a variable, and that is in fact an identifier, doesn't designates a variable in the sense of a "chunk of memory whose content can change" but references an object to which the identifier is binded, object whose value cannot change because it is an immutable object.
Please read the explanations of the documentation on the data model and the execution model of Python which is quite different from the ones of languages such as Java, PHP, etc.

SyntaxError: keyword can't be an expression while creating a dictionary

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?
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'}
>>> name = 'rack.session'
>>> val = 'CookieVal'
>>> cookies = {name: val}
>>> cookies
{'rack.session': 'CookieVal'}
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.
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
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.
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'}
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

Easiest way to substitute characters in the string

Suppose I have a main form named "main_form" and I have few more forms name like "w_main_form","g_main_form" etc etc which are based on "main_form" and they vary according to the 'category'.
Now is there any easy way to generate names of derived forms and how to call them.
Suppose the category is "iron" then the form name should be "w_main_form" and when the category is "coal" the form name should be "g_main_form".
>>> main_name = "main_form"
>>> derived_names = []
>>> for prefix in ["w_", "g_"]:
derived_names.append("%s%s" % (prefix, main_name))
>>> derived_names
['w_main_form', 'g_main_form']
Or, with list comprehensions (my preferred method):
>>> derived_names = ["%s%s" % (prefix, main_name) for prefix in ["w_", "g_"]]
>>> derived_names
['w_main_form', 'g_main_form']
In general, so you can apply the same principle yourself, you want to think of the transform you want to do in terms of a function, f(main_name, data), and the data to provide to it. In this case, the operation was "prepend" (which I implemented with "%s%s" % (prefix, main_name)) and the data was all the prefixes.
EDIT: Yes.
>>> category_to_prefix = {'iron': 'w_', 'coal': 'g_'}
>>> def category_to_form_name(category):
return '%s%s' % (category_to_prefix.get(category,""), 'main_form')
>>> category_to_form_name('iron')
'w_main_form'
>>> category_to_form_name('coal')
'g_main_form'
>>> category_to_form_name(None)
'main_form'
Please upvote and accept the answer (click the up arrow and the green checkmark) if it is what you were looking for.
This will do what your comment stated ..
def generate_Name(base, category):
if category == 'iron':
derived_name = 'w_'+base
elif category == 'coal':
derived_name = 'g_'+base
return derived_name
iron_form = generate_Name('main_form', 'iron')
coal_form = generate_Name('main_form', 'coal')
print iron_form
print coal_form
gives
w_main_form
g_main_form

Categories