How do I create variable variables?

I know that some other languages, such as PHP, support a concept of “variable variable names” – that is, the contents of a string can be used as part of a variable name.

I heard that this is a bad idea in general, but I think it would solve some problems I have in my Python code.

Is it possible to do something like this in Python? What can go wrong?


If you are just trying to look up an existing variable by its name, see How can I select a variable by (string) name?. However, first consider whether you can reorganize the code to avoid that need, following the advice in this question.

8

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

>>> dct = {'x': 1, 'y': 2, 'z': 3}
>>> dct
{'x': 1, 'y': 2, '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:

lst = ['foo', 'bar', 'baz']
print(lst[1])           # prints bar, because indices start at 0
lst.append('potatoes')  # lst 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.

0

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'

0

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.

6

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.

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”.

0

Use globals() (disclaimer: this is a bad practice, but is the most straightforward answer to your question, please use other data structure as in the accepted answer).

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_2i_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'

0

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'])
v = Variables(34, 45)
print(v.first, v.second)

1

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(**variables)
setattr(a,"g","G")
a.g = "G+"
something = a.a

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

2

Variable variables in Python

"""
<?php
$a = 'hello';
$e = 'wow'
?>
<?php
$$a = 'world';
?>
<?php
echo "$a ${$a}n";
echo "$a ${$a[1]}n";
?>
<?php
echo "$a $hello";
?>
"""

a = 'hello'  #<?php $a = 'hello'; ?>
e = 'wow'   #<?php $e = 'wow'; ?>
vars()[a] = 'world' #<?php $$a = 'world'; ?>
print(a, vars()[a]) #<?php echo "$a ${$a}n"; ?>
print(a, vars()[vars()['a'][1]]) #<?php echo "$a ${$a[1]}n"; ?>
print(a, hello) #<?php echo "$a $hello"; ?>

Output:

hello world
hello wow
hello world

Using globals(), locals(), or vars() will produce the same results

#<?php $a = 'hello'; ?>
#<?php $e = 'wow'; ?>
#<?php $$a = 'world'; ?>
#<?php echo "$a ${$a}n"; ?>
#<?php echo "$a ${$a[1]}n"; ?>
#<?php echo "$a $hello"; ?>

print('locals():n')
a = 'hello'
e = 'wow'
locals()[a] = 'world'
print(a, locals()[a])
print(a, locals()[locals()['a'][1]])
print(a, hello)

print('nnglobals():n')
a = 'hello'
e = 'wow'
globals()[a] = 'world'
print(a, globals()[a])
print(a, globals()[globals()['a'][1]])
print(a, hello)

Output:

locals():

hello world
hello wow
hello world


globals():

hello world
hello wow
hello world

Bonus (creating variables from strings)

# Python 2.7.16 (default, Jul 13 2019, 16:01:51)
# [GCC 8.3.0] on linux2

Creating variables and unpacking tuple:

g = globals()
listB = []
for i in range(10):
    g["num%s" % i] = i ** 10
    listB.append("num{0}".format(i))

def printNum():
    print "Printing num0 to num9:"
    for i in range(10):
        print "num%s = " % i, 
        print g["num%s" % i]

printNum()

listA = []
for i in range(10):
    listA.append(i)

listA = tuple(listA)
print listA, '"Tuple to unpack"'

listB = str(str(listB).strip("[]").replace("'", "") + " = listA")

print listB

exec listB

printNum()

Output:

Printing num0 to num9:
num0 =  0
num1 =  1
num2 =  1024
num3 =  59049
num4 =  1048576
num5 =  9765625
num6 =  60466176
num7 =  282475249
num8 =  1073741824
num9 =  3486784401
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) "Tuple to unpack"
num0, num1, num2, num3, num4, num5, num6, num7, num8, num9 = listA
Printing num0 to num9:
num0 =  0
num1 =  1
num2 =  2
num3 =  3
num4 =  4
num5 =  5
num6 =  6
num7 =  7
num8 =  8
num9 =  9

1

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

I’m 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. (Editor’s note: It is now closed as a duplicate of How can I select a variable by (string) name?)


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'

1

I have tried both in python 3.7.3, you can use either globals() or vars()

>>> food #Error
>>> milkshake #Error
>>> food="bread"
>>> drink="milkshake"
>>> globals()[food] = "strawberry flavor"
>>> vars()[drink] = "chocolate flavor"
>>> bread
'strawberry flavor'
>>> milkshake
'chocolate flavor'
>>> globals()[drink]
'chocolate flavor'
>>> vars()[food]
'strawberry flavor'

Reference:
https://www.daniweb.com/programming/software-development/threads/111526/setting-a-string-as-a-variable-name#post548936

0

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)

0

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

It should be extremely risky…
but you can use exec():

a = 'b=5'
exec(a)
c = b*2
print (c)

Result:
10

2

The setattr() method sets the value of the specified attribute of the specified object.

Syntax goes like this –

setattr(object, name, value)
Example –

setattr(self,id,123)

which is equivalent to self.id = 123

As you might have observed, setattr() expects an object to be passed along with the value to generate/modify a new attribute.

We can use setattr() with a workaround to be able to use within modules. Here’ how –

import sys
x = "pikachu"
value = 46
thismodule = sys.modules[__name__]
setattr(thismodule, x, value)
print(pikachu)

1

TL;DR: Consider using eval()

I found this page because I was looking to do some simple template processing with python string functions (short of including a full blown template engine). I was searching for how to set local variables, and that’s how I got here.

My problem began with a simple template:

Hello, {name}

The way I populated this template was this way:

def populate(template,variables):
    return template.format(**variables)

And so this would work:

values = {
  'name' : 'Stack Overflow' 
}
my_template = "Hello, {name}"
print( populate( my_template , values ) )

# output
Hello, Stack Overflow

But then things went south fast. I tried a new template where I only wanted the first word:

Now my template was this: "Hello, {name.split()[0]}" and this code got an error.

values['name'] = "Stack Overflow"
my_template = "Hello, {name.split()[0]}"
print( populate( my_template , values ) 
# output (well, stderr)
AttributeError: 'str' object has no attribute 'split()'. Did you mean: 'split'?

And then I learned that the format function doesn’t work the way I want it. You can’t pass arbitrary code to it. You need to pass it formatting stuff. And so I tried a different solution. I coded populate to use eval and an f-string instead of format. An f-string (unlike format) allows for python code in the curly brace interpolation. So an f-string like this `f”Hello, {name.split()[0]}” does work. Let’s just see the code for this small part (so you don’t have to leave this post to figure out f-string):

name = "Stack Overflow"
print(f"Hello, {name.split()[0]}")
# Output:
Hello, Stack

Now I just had to use an f-string. So I used eval. My new populate is this:

def populate(template,variables):
    return eval(f'f"{template}"')

But when I ran the program again, I got this error:

NameError: name 'name' is not defined

I should point out that an f-string is able to populate the string with any global or local variable in scope. To fix my issue, I could change my template to "Hello, {variables['name']}" since variables is definitely in scope. This is really bad approach because now the template writer has to know about a the variables dictionary. Rather, I want to make every key available in the variables dictionary available to the template author, as I had before with format(**variables).

To solve my problem, I wanted to set local variables based on the content of the variables dictionary passed to the populate() function.

I tried this:

locals() = variables

And that didn’t work:

    locals() = variables
    ^^^^^^^^
SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='?

And then I tried this and this worked:

def populate(template,variables):
    for k,v in variables.items():
      locals()[k] = v
    return eval(f'f"{template}"')


values = {
  'name' : 'Stack Overflow'
}
my_template = "Hello, {name.split()[0]}"
print( populate( my_template , values ) )

And so the first take away is that you can create local variables in a function (or globals for that matter) by setting a key value pair in the locals() dictionary.

In the case of eval, the second and third parameters allow you to pass in local and global variables, and so you could simplify the populate function to just this:

def populate(template,variables):
    return eval(f'f"{template}"',variables)

The above is how I used eval to do f-string population (or simplistic template evaluation). But eval can also be used to provide variable variables.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật