user20955
user20955

Reputation: 2622

Dynamically create variables inside function

I want to create variables inside a function from a dictionary.

Let's say I have a dictionary, bar:

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

That goes to:

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

I want to make new variables with the variable names as bar's keys (a, b, c), then set the values of the variables to the value of the corresponding key.

So, in the end, it should be similar to:

bar = {
    k: v
}
# ---> 
def foo():
    k = v 

Is it possible? And if so, how?

Upvotes: 2

Views: 1518

Answers (4)

Brian
Brian

Reputation: 119221

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.

Upvotes: 3

user20955
user20955

Reputation: 2622

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

Upvotes: 1

tzot
tzot

Reputation: 95921

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?

Upvotes: 3

Brian
Brian

Reputation: 119221

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)

Upvotes: 1

Related Questions