tags:

views:

387

answers:

4

I want to create variables inside function from dictionary.

Lets say I have a dictionary

bar = {'a': 1, 'b': 2, 'c': 3}

and function

def foo():
  pass

What I want to do is to create inside function "foo" variables with names of each dictionary item name and values as dictionary item values

So in the end it should be similar to

def foo():
  a = 1
  b = 2
  c = 3

Is it possible at all? And if it does, how to do such thing?

+1  A: 

Why would you want to do such a thing? Unless you actually do anything with the variables inside the function, a function that just assigns several variables and then discards them is indistinguishable to def foo(): pass (An optimiser would be justified in generating exactly the same bytecode).

If you also want to dynamically append code that uses the values, then you could do this by using exec (though unless this is really user-input code, there are almost certainly better ways to do what you want). eg:

some_code = '  return a+b+c'
exec "def foo():\n  " + '\n  '.join('%s = %s' for k,v in bar.items()) + '\n' + some_code

(Note that your code must be indented to the same level.)

On the other hand, if you want to actually assign these values to the function object (so you can do foo.a and get 1 - note that your sample code doesn't do this), you can do this by:

for key, val in bar.items():
    setattr(foo, key, val)
Brian
+2  A: 

Your question is not clear.

If you want to "set" said variables when foo is not running, no, you can't. There is no frame object yet to "set" the local variables in.

If you want to do that in the function body, you shouldn't (check the python documentation for locals()).

However, you could do a foo.__dict__.update(bar), and then you could access those variables even from inside the function as foo.a, foo.b and foo.c. The question is: why do you want to do that, and why isn't a class more suitable for your purposes?

ΤΖΩΤΖΙΟΥ
+1  A: 

Thanks guys, I got the point. I should not do such thing. But if your curios what I tried to do is to somehow short number of lines in my view function in django. I have form with many fields, and instead of receive every field in form of:

first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name'] ..

i was thinking to take every attribute name of my form class and loop over it. Like so:

for name in ProfileRegistration.base_fields.__dict__['keyOrder']:
   # and here the variables that i tried to assign
+3  A: 

From your comment, perhaps what you're really looking for is something like a bunch object:

class Bunch(object):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

b=Bunch(**form.cleaned_data)

print b.first_name, b.last_name

(The ** syntax is because Bunch-type objects are usually used like Bunch(foo=12, bar='blah') - not used in your case but I've left it for consistency with normal usage)

This does require a "b." prefix to access your variables, but if you think about it, this is no bad thing. Consider what would happen if someone crafted a POST request to overwrite variables you aren't expecting to be overwritten - it makes it easy to produce crashes and DOS attacks, and could easily introduce more serious security vulnerabilities.

Brian