I want to create variables dynamically in Python. Does anyone have any creative means of doing this?
-
3Can you explain "via to a while loop?" I have no idea what that means.wheaties– wheaties2011-02-18 01:16:09 +00:00Commented Feb 18, 2011 at 1:16
-
2To solve what problem? Need some context.Mike– Mike2011-02-18 01:16:11 +00:00Commented Feb 18, 2011 at 1:16
-
I'm wanting to create a while loop and inside that loop have it create variables over and over until I tell it to stop. Does this make any sense?Noah R– Noah R2011-02-18 01:18:03 +00:00Commented Feb 18, 2011 at 1:18
-
2what do you mean 'dynamically create variables?' Dynamically how? Can you just use a dictionary and assign various values of it?Gordon Gustafson– Gordon Gustafson2011-02-18 01:23:44 +00:00Commented Feb 18, 2011 at 1:23
-
10@Trivikram: Incorrect, the variable scope is the entire function, not just the while loop.Gintautas Miliauskas– Gintautas Miliauskas2011-02-18 01:24:51 +00:00Commented Feb 18, 2011 at 1:24
8 Answers
Unless there is an overwhelming need to create a mess of variable names, I would just use a dictionary, where you can dynamically create the key names and associate a value to each.
a = {}
k = 0
while k < 10:
# dynamically create key
key = ...
# calculate value
value = ...
a[key] = value
k += 1
There are also some interesting data structures in the collections module that might be applicable.
12 Comments
a isn't very different from creating the same in locals() or globals() that are implemented as dictionaries too. I wonder why I have been downvoted by some downvote sniper for my answer creating an item in globals() while the answer of Gintautas Miliauskas is upvoted and this answer that doesn't give the how-to for <dynamically create key> is upvoted 3 times.locals() function creates a dictionary from the local variables but the dictionary doesn't exist unless you call locals().locals(). The exception is in Python 2.x when you use exec inside a function without specifying a local namespace for the exec. I'm not sure offhand where this is documented: it isn't part of the language definition because different implementations can choose differently how to implement the locals namespace.globals() returns a dictionary of the module's variables. You can create a new variable by creating a key on that dictionary:
# By default, a module has some hidden variables defined
print({k: v for k, v in globals().items() if not k.startswith("__")})
for i in range(1, 11):
globals()[f"my_variable_{i}"] = i
print()
print(my_variable_1)
print(my_variable_2)
# and so on
print()
print({k: v for k, v in globals().items() if not k.startswith("__")})
Result:
{}
1
2
{'i': 10, 'my_variable_1': 1, 'my_variable_2': 2, 'my_variable_3': 3, 'my_variable_4': 4, 'my_variable_5': 5, 'my_variable_6': 6, 'my_variable_7': 7, 'my_variable_8': 8, 'my_variable_9': 9, 'my_variable_10': 10}
18 Comments
globals() will go on the module namespace and stay there until the end of the program. Most of the times when one says "variable" they mean a function local variable, which only exists in the context of the execution of a function. In this case globals() is likely not the solution to the problem. Consider explicitly using a dictionary, as in the answer provided by JoshAdel.Use the exec() method to run arbitrary code. For example, say you have a dictionary and you want to turn each key into a variable with its original dictionary value, you can do the following:
>>> c = {"one": 1, "two": 2}
>>> for k, v in c.items():
... exec(f"{k} = {v}")
...
>>> one
1
>>> two
2
9 Comments
globals() dict, or calling setattr() on the module object."send_me_all_your_private_data()" and get it executed on your machine.Stuffing things into the global and/or local namespaces is not a good idea. Using a dict is so some-other-language-ish ... d['constant-key'] = value just looks awkward. Python is OO. In the words of a master: """Namespaces are one honking great idea -- let's do more of those!"""
Like this:
>>> class Record(object):
... pass
...
>>> r = Record()
>>> r.foo = 'oof'
>>> setattr(r, 'bar', 'rab')
>>> r.foo
'oof'
>>> r.bar
'rab'
>>> names = 'id description price'.split()
>>> values = [666, 'duct tape', 3.45]
>>> s = Record()
>>> for name, value in zip(names, values):
... setattr(s, name, value)
...
>>> s.__dict__ # If you are suffering from dict withdrawal symptoms
{'price': 3.45, 'id': 666, 'description': 'duct tape'}
>>>
6 Comments
vars()['meta_anio_2012'] = 'translate'
2 Comments
locals()['meta_anio_2012'] = 'translate', which won't work in a function and is specifically warned against in the documentation. It also suffers from many of the problems pointed out in the comments to other answers.vars(sys.modules[__name__])['my_variable'] = 'value' There is nothing wrong with doing this as it fetches the underlying object's __dict__. The only time this may not work is if the object being fetched has write permissions on attributes.Keyword parameters allow you to pass variables from one function to another. In this way you can use the key of a dictionary as a variable name (which can be populated in your while loop). The dictionary name just needs to be preceded by ** when it is called.
# create a dictionary
>>> kwargs = {}
# add a key of name and assign it a value, later we'll use this key as a variable
>>> kwargs['name'] = 'python'
# an example function to use the variable
>>> def print_name(name):
... print name
# call the example function
>>> print_name(**kwargs)
python
Without **, kwargs is just a dictionary:
>>> print_name(kwargs)
{'name': 'python'}
Comments
NOTE: This should be considered a discussion rather than an actual answer.
An approximate approach is to operate __main__ in the module you want to create variables. For example there's a b.py:
#!/usr/bin/env python
# coding: utf-8
def set_vars():
import __main__
print '__main__', __main__
__main__.B = 1
try:
print B
except NameError as e:
print e
set_vars()
print 'B: %s' % B
Running it would output
$ python b.py
name 'B' is not defined
__main__ <module '__main__' from 'b.py'>
B: 1
But this approach only works in a single module script, because the __main__ it import will always represent the module of the entry script being executed by python, this means that if b.py is involved by other code, the B variable will be created in the scope of the entry script instead of in b.py itself. Assume there is a script a.py:
#!/usr/bin/env python
# coding: utf-8
try:
import b
except NameError as e:
print e
print 'in a.py: B', B
Running it would output
$ python a.py
name 'B' is not defined
__main__ <module '__main__' from 'a.py'>
name 'B' is not defined
in a.py: B 1
Note that the __main__ is changed to 'a.py'.
1 Comment
new_var = eval('old_var' + str(count))For free-dom:
import random
alphabet = tuple('abcdefghijklmnopqrstuvwxyz')
globkeys = globals().keys()
globkeys.append('globkeys') # because name 'globkeys' is now also in globals()
print 'globkeys==',globkeys
print
print "globals().keys()==",globals().keys()
for i in xrange(8):
globals()[''.join(random.sample(alphabet,random.randint(3,26)))] = random.choice(alphabet)
del i
newnames = [ x for x in globals().keys() if x not in globkeys ]
print
print 'newnames==',newnames
print
print "globals().keys()==",globals().keys()
print
print '\n'.join(repr((u,globals()[u])) for u in newnames)
Result
globkeys== ['__builtins__', 'alphabet', 'random', '__package__', '__name__', '__doc__', 'globkeys']
globals().keys()== ['__builtins__', 'alphabet', 'random', '__package__', '__name__', 'globkeys', '__doc__']
newnames== ['fztkebyrdwcigsmulnoaph', 'umkfcvztleoij', 'kbutmzfgpcdqanrivwsxly', 'lxzmaysuornvdpjqfetbchgik', 'wznptbyermclfdghqxjvki', 'lwg', 'vsolxgkz', 'yobtlkqh']
globals().keys()== ['fztkebyrdwcigsmulnoaph', 'umkfcvztleoij', 'newnames', 'kbutmzfgpcdqanrivwsxly', '__builtins__', 'alphabet', 'random', 'lxzmaysuornvdpjqfetbchgik', '__package__', 'wznptbyermclfdghqxjvki', 'lwg', 'x', 'vsolxgkz', '__name__', 'globkeys', '__doc__', 'yobtlkqh']
('fztkebyrdwcigsmulnoaph', 't')
('umkfcvztleoij', 'p')
('kbutmzfgpcdqanrivwsxly', 'a')
('lxzmaysuornvdpjqfetbchgik', 'n')
('wznptbyermclfdghqxjvki', 't')
('lwg', 'j')
('vsolxgkz', 'w')
('yobtlkqh', 'c')
Another way:
import random
pool_of_names = []
for i in xrange(1000):
v = 'LXM'+str(random.randrange(10,100000))
if v not in globals():
pool_of_names.append(v)
alphabet = 'abcdefghijklmnopqrstuvwxyz'
print 'globals().keys()==',globals().keys()
print
for j in xrange(8):
globals()[pool_of_names[j]] = random.choice(alphabet)
newnames = pool_of_names[0:j+1]
print
print 'globals().keys()==',globals().keys()
print
print '\n'.join(repr((u,globals()[u])) for u in newnames)
result:
globals().keys()== ['__builtins__', 'alphabet', 'random', '__package__', 'i', 'v', '__name__', '__doc__', 'pool_of_names']
globals().keys()== ['LXM7646', 'random', 'newnames', 'LXM95826', 'pool_of_names', 'LXM66380', 'alphabet', 'LXM84070', '__package__', 'LXM8644', '__doc__', 'LXM33579', '__builtins__', '__name__', 'LXM58418', 'i', 'j', 'LXM24703', 'v']
('LXM66380', 'v')
('LXM7646', 'a')
('LXM8644', 'm')
('LXM24703', 'r')
('LXM58418', 'g')
('LXM84070', 'c')
('LXM95826', 'e')
('LXM33579', 'j')
10 Comments
globals()['X'] to create a new object with name X that will be used as following: li.append(X) etc etc;v = 48 or for i in xrange(20) . I think that it's for a great part because writing globals()["v"] = 48 looks long and weird that it is badly considered. But where is the real weirdness in that ? I don'y understand.