By Pyornide


2009-09-03 12:37:48 8 Comments

How do I accomplish variable variables in Python?

Here is an elaborative manual entry, for instance: Variable variables

I have heard this is a bad idea in general though, and it is a security hole in Python. Is that true?

16 comments

@Kelvin 2019-03-14 12:30:25

you can use the built-in function vars()

>>> foo = 'bar'
>>> vars()[foo] = 'something'
>>> bar
'something'

@intellimath 2019-01-03 21:39:23

There is a known method to emulate a container for variables, which support both methods of access: by a variable's name and a string key.

class Vars:
    def __init__(self, **kw):
        self.__dict__.update(kw)

    def __getitem__(self, key):
        return self.__dict__[key]

    def __setitem__(self, key, val):
        self.__dict__[key] = val

    def __contains__(self, name):
        return name in self.__dict__

    def __nonzero__(self):
        return bool(self.__dict__)

    def __iter__(self):
        return iter(self.__dict__)

    def __len__(self):
        return len(self.__dict__)

    def __copy__(self):
        return self.__class__(**self.__dict__)

    def __repr__(self):
        return 'Vars(' + ', '.join('%s=%r' % (k,v) for k,v in self.__dict__.items()) + ')'

>>> vars = Vars()
>>> vars.a = 1
>>> vars['b'] = 2
>>> print(vars)
Vars(a=1, b=2)
>>> print(vars['a'], vars.b)
1 2
>>> print(tuple(vars))
('a', 'b')

@Rocky Li 2018-11-27 15:34:22

Use globals()

You can actually assign variables to global scope dynamically, for instance, if you want 10 variables that can be accessed on a global scope i_1, i_2 ... i_10:

for i in range(10):
    globals()['i_{}'.format(i)] = 'a'

This will assign 'a' to all of these 10 variables, of course you can change the value dynamically as well. All of these variables can be accessed now like other globally declared variable:

>>> i_5
'a'

@Sayali Sonawane 2018-11-20 19:32:27

Please refer following example to create variables runtime. You can use globals().

for i in range(3):
    globals() ['variable_'+str(i)] = i

In the above example, I want to create three variables: variable_0, variable_1 and variable_2 at runtime with values 0,1 and 2 respectively.

variable_0
[Output]:0

variable_1
[Output]:1

variable_2
[Output]:2

To access the value of variables created at runtime, you can use eval() method as follows:

for i in range(3):
globals() ['variable_'+str(i)] = i
print('Variable Value:',eval('variable_'+str(i)))

[Output]:
Variable Value: 0
Variable Value: 1
Variable Value: 2

@c_harm 2009-09-03 12:41:05

You can use dictionaries to accomplish this. Dictionaries are stores of keys and values.

>>> dct = {'x': 1, 'y': 2, 'z': 3}
>>> dct
{'y': 2, 'x': 1, 'z': 3}
>>> dct["y"]
2

You can use variable key names to achieve the effect of variable variables without the security risk.

>>> x = "spam"
>>> z = {x: "eggs"}
>>> z["spam"]
'eggs'

For cases where you're thinking of doing something like

var1 = 'foo'
var2 = 'bar'
var3 = 'baz'
...

a list may be more appropriate than a dict. A list represents an ordered sequence of objects, with integer indices:

l = ['foo', 'bar', 'baz']
print(l[1])           # prints bar, because indices start at 0
l.append('potatoes')  # l is now ['foo', 'bar', 'baz', 'potatoes']

For ordered sequences, lists are more convenient than dicts with integer keys, because lists support iteration in index order, slicing, append, and other operations that would require awkward key management with a dict.

@Corey D 2009-09-03 12:44:40

@Guillaume Lebreton 2017-10-23 19:24:10

If you don't want to use any object, you can still use setattr() inside your current module:

import sys
current_module = module = sys.modules[__name__]  # i.e the "file" where your code is written
setattr(current_module, 'variable_name', 15)  # 15 is the value you assign to the var
print(variable_name)  # >>> 15, created from a string

@fralau 2017-12-30 21:13:21

This one sounds better to me than using 'exec'.

@Alexey 2018-01-30 18:25:02

This does not work with __dict__ variable however. I wonder if there is a general mechanism to create any global variable dynamically.

@Guillaume Lebreton 2018-01-31 07:42:21

globals() can do this

@Bill Oldroyd 2017-09-17 22:38:50

The SimpleNamespace class could be used to create new attributes with setattr, or subclass SimpleNamespace and create your own function to add new attribute names (variables).

from types import SimpleNamespace

variables = {"b":"B","c":"C"}
a = SimpleNamespace(**v)
setattr(a,"g","G")
a.g = "G+"
something = a.a

@Alexey Rodimov 2017-08-11 21:13:57

Any set of variables can also be wrapped up in a class. "Variable" variables may be added to the class instance during runtime by directly accessing the built-in dictionary through __dict__ attribute.

The following code defines Variables class, which adds variables (in this case attributes) to its instance during the construction. Variable names are taken from a specified list (which, for example, could have been generated by program code):

# some list of variable names
L = ['a', 'b', 'c']

class Variables:
    def __init__(self, L):
        for item in L:
            self.__dict__[item] = 100

v = Variables(L)
print(v.a, v.b, v.c)
#will produce 100 100 100

@Andriy Ivaneyko 2016-06-09 12:14:11

You have to use globals() built in method to achieve that behaviour:

def var_of_var(k, v):
    globals()[k] = v

print variable_name # NameError: name 'variable_name' is not defined
some_name = 'variable_name'
globals()[some_name] = 123
print variable_name # 123

some_name = 'variable_name2'
var_of_var(some_name, 456)
print variable_name2 # 456

@Nadia Alramli 2009-09-03 12:43:49

It's not a good idea. If you are accessing a global variable you can use globals().

>>> a = 10
>>> globals()['a']
10

If you want to access a variable in the local scope you can use locals(), but you cannot assign values to the returned dict.

A better solution is to use getattr or store your variables in a dictionary and then access them by name.

@Glenn Maynard 2009-09-03 18:43:16

Don't forget to mention that you can't modify variables through locals() (docs.python.org/library/functions.html#locals).

@sudo 2016-06-06 18:51:03

You can't set variables this way. You can't do globals()['a'] = 10.

@oxidworks 2017-01-02 16:10:48

Thx, also working with locals()['x'] = "xxx"

@PM 2Ring 2017-11-17 12:20:02

@oxidworks No, it's not working. However, it may seem to work if you're in the global context, where locals() simply returns the globals() dict.

@berkelem 2018-08-30 02:29:45

Why not use vars() built-in dictionary?

@patapouf_ai 2016-11-02 15:53:20

I'm am answering the question: How to get the value of a variable given its name in a string? which is closed as a duplicate with a link to this question.

If the variables in question are part of an object (part of a class for example) then some useful functions to achieve exactly that are hasattr, getattr, and setattr.

So for example you can have:

class Variables(object):
    def __init__(self):
        self.foo = "initial_variable"
    def create_new_var(self,name,value):
        setattr(self,name,value)
    def get_var(self,name):
        if hasattr(self,name):
            return getattr(self,name)
        else:
            raise("Class does not have a variable named: "+name)

Then you can do:

v = Variables()
v.get_var("foo")

"initial_variable"

v.create_new_var(v.foo,"is actually not initial")
v.initial_variable

"is actually not initial"

@TigerhawkT3 2016-08-16 10:41:07

New coders sometimes write code like this:

my_calculator.button_0 = tkinter.Button(root, text=0)
my_calculator.button_1 = tkinter.Button(root, text=1)
my_calculator.button_2 = tkinter.Button(root, text=2)
...

The coder is then left with a pile of named variables, with a coding effort of O(m * n), where m is the number of named variables and n is the number of times that group of variables needs to be accessed (including creation). The more astute beginner observes that the only difference in each of those lines is a number that changes based on a rule, and decides to use a loop. However, they get stuck on how to dynamically create those variable names, and may try something like this:

for i in range(10):
    my_calculator.('button_%d' % i) = tkinter.Button(root, text=i)

They soon find that this does not work.

If the program requires arbitrary variable "names," a dictionary is the best choice, as explained in other answers. However, if you're simply trying to create many variables and you don't mind referring to them with a sequence of integers, you're probably looking for a list. This is particularly true if your data are homogeneous, such as daily temperature readings, weekly quiz scores, or a grid of graphical widgets.

This can be assembled as follows:

my_calculator.buttons = []
for i in range(10):
    my_calculator.buttons.append(tkinter.Button(root, text=i))

This list can also be created in one line with a comprehension:

my_calculator.buttons = [tkinter.Button(root, text=i) for i in range(10)]

The result in either case is a populated list, with the first element accessed with my_calculator.buttons[0], the next with my_calculator.buttons[1], and so on. The "base" variable name becomes the name of the list and the varying identifier is used to access it.

Finally, don't forget other data structures, such as the set - this is similar to a dictionary, except that each "name" doesn't have a value attached to it. If you simply need a "bag" of objects, this can be a great choice. Instead of something like this:

keyword_1 = 'apple'
keyword_2 = 'banana'

if query == keyword_1 or query == keyword_2:
    print('Match.')

You will have this:

keywords = {'apple', 'banana'}
if query in keywords:
    print('Match.')

Use a list for a sequence of similar objects, a set for an arbitrarily-ordered bag of objects, or a dict for a bag of names with associated values.

@ojas mohril 2016-06-22 15:09:32

Instead of a dictionary you can also use namedtuple from the collections module, which makes access easier.

for example:

#using dictionary
variables = {}
variables["first"] = 34
variables["second"] = 45
print variables["first"], variables["second"]

#using namedtuple
Variables = namedtuple('Variables', ['first', 'second'])
vars = Variables(34, 45)
print vars.first, vars.second

@DomTomCat 2016-06-09 11:47:06

The consensus is to use a dictionary for this - see the other answers. This is a good idea for most cases, however, there are many aspects arising from this:

  • you'll yourself be responsible for this dictionary, including garbage collection (of in-dict variables) etc.
  • there's either no locality or globality for variable variables, it depends on the globality of the dictionary
  • if you want to rename a variable name, you'll have to do it manually
  • however, you are much more flexible, e.g.
    • you can decide to overwrite existing variables or ...
    • ... choose to implement const variables
    • to raise an exception on overwriting for different types
    • etc.

That said, I've implemented a variable variables manager-class which provides some of the above ideas. It works for python 2 and 3.

You'd use the class like this:

from variableVariablesManager import VariableVariablesManager

myVars = VariableVariablesManager()
myVars['test'] = 25
print(myVars['test'])

# define a const variable
myVars.defineConstVariable('myconst', 13)
try:
    myVars['myconst'] = 14 # <- this raises an error, since 'myconst' must not be changed
    print("not allowed")
except AttributeError as e:
    pass

# rename a variable
myVars.renameVariable('myconst', 'myconstOther')

# preserve locality
def testLocalVar():
    myVars = VariableVariablesManager()
    myVars['test'] = 13
    print("inside function myVars['test']:", myVars['test'])
testLocalVar()
print("outside function myVars['test']:", myVars['test'])

# define a global variable
myVars.defineGlobalVariable('globalVar', 12)
def testGlobalVar():
    myVars = VariableVariablesManager()
    print("inside function myVars['globalVar']:", myVars['globalVar'])
    myVars['globalVar'] = 13
    print("inside function myVars['globalVar'] (having been changed):", myVars['globalVar'])
testGlobalVar()
print("outside function myVars['globalVar']:", myVars['globalVar'])

If you wish to allow overwriting of variables with the same type only:

myVars = VariableVariablesManager(enforceSameTypeOnOverride = True)
myVars['test'] = 25
myVars['test'] = "Cat" # <- raises Exception (different type on overwriting)

@markroxor 2018-02-19 06:17:18

At first glance the long camelised imports made me think this was Java.

@SilentGhost 2009-09-03 12:43:26

Use the built-in getattr function to get an attribute on an object by name. Modify the name as needed.

obj.spam = 'eggs'
name = 'spam'
getattr(obj, name)  # returns 'eggs'

@kap 2015-06-26 08:29:58

That works great with a namedtuple

@rayryeng 2016-11-18 23:01:27

Lovely. This is exactly what I needed. I have an object and needed to access variables by a string and I didn't want to use eval. Thanks!

@sepp2k 2009-09-03 12:42:00

Whenever you want to use variable variables, it's probably better to use a dictionary. So instead of writing

$foo = "bar"
$$foo = "baz"

you write

mydict = {}
foo = "bar"
mydict[foo] = "baz"

This way you won't accidentally overwrite previously existing variables (which is the security aspect) and you can have different "namespaces".

Related Questions

Sponsored Content

36 Answered Questions

[SOLVED] How do I check if a list is empty?

  • 2008-09-10 06:20:11
  • Ray Vega
  • 2167205 View
  • 3207 Score
  • 36 Answer
  • Tags:   python list

14 Answered Questions

[SOLVED] How to return multiple values from a function?

27 Answered Questions

[SOLVED] How do I list all files of a directory?

  • 2010-07-08 19:31:22
  • duhhunjonn
  • 3132136 View
  • 3429 Score
  • 27 Answer
  • Tags:   python directory

44 Answered Questions

[SOLVED] How to merge two dictionaries in a single expression?

42 Answered Questions

[SOLVED] How do I sort a dictionary by value?

42 Answered Questions

[SOLVED] How do I check whether a file exists without exceptions?

25 Answered Questions

[SOLVED] How can I safely create a nested directory in Python?

24 Answered Questions

[SOLVED] How do I pass a variable by reference?

18 Answered Questions

[SOLVED] Using global variables in a function

8 Answered Questions

[SOLVED] Getting the class name of an instance?

Sponsored Content