I've been wondering if there is a way to use an iterator as a variable name in a Python loop. For example, if I wanted to create objects v0, v1, v2, is there a way to do something like this:

for i in range(3):v + str(i) = i**2

I know the syntax is wrong, but the idea should be clear. Something equivalent to paste in R? Thanks much,

5

Best Answer


The builtin method globals() returns a dictionary representing the current global symbol table.

You can add a variable to globals like this:

globals()["v" + str(i)] = i**2

FYI: This is the answer to your question but certainly not the recommended way to go. Directly manipulating globals is hack-solution that can mostly be avoided be some cleaner alternative. (See other comments in this thread)

While this does not attempt to answer the question directly (see geccos answer for that), this is generally the "approved" method for such an operation:

v = [i**2 for i in range(3)]print v[0] # 0print v[1] # 1print v[2] # 4

In general it is both cleaner and more extensible to use an ADT (a list in this case) to represent the given problem than trying to create "dynamic variables" or "variable variables".

Happy coding.


While the above uses indices, the more general form of "variable variables" is generally done with a dictionary:

names = dict(("v" + str(i), i**2) for i in range(3))print names["v2"] # 4

And, for a fixed finite (and relatively small) set of variables, "unpacking" can also be used:

v0, v1, v2 = [i**2 for i in range(3)]print v1 # 1

There are a few ways to do this, the best will depend on what you actually want to do with the variables after you've created them.

globals() and locals() will work but they're not what you want. exec() will also work but it's even worse than globals() and locals().

A list comprehension as mentioned by @user166390 is a good idea if v1, v2 and v3 are homogenous and you just want to access them by index.

>>> v = [i ** 2 for i in range(3)]>>> v[0]0>>> v[1]1>>> v[2]4

You could also do this, if it's always exactly three elements:

>>> v1, v2, v3 = [i ** 2 for i in range(3)]>>> v10>>> v21>>> v32

This is nice if the objects are more individual because you can give them their own names.

Another in-between option is to use a dict:

d = {}for i, val in enumerate(range(3)):d["v{}".format(i)] = val>>> d["v0"]0>>> d["v1"]1>>> d["v2"]4

Or a shortcut for the above using a dict comprehension:

d = {"v{}".format(i): val for i, val in enumerate(range(3))}

I prefer xrange() to range(). Here the code for you:

for i in xrange(3):exec("v"+str(i)+" = i * i")

Even if... you should consider using a list

# Python 3.8.2 (default, Feb 26 2020, 02:56:10)

Creating variable names using globals() and unpacking a tuple using exec():

glo = globals()listB=[]for i in range(1,11):glo["v%s" % i] = i * 10listB.append("v%s" % i)def print1to10():print("Printing v1 to v10:")for i in range(1,11):print("v%s = " % i, end="")print(glo["v%s" % i])print1to10()listA=[]for i in range(1,11):listA.append(i)listA=tuple(listA)print(listA, '"Tuple to unpack"')listB = str(str(listB).strip("[]").replace("'", "") + " = listA")print(listB)exec(listB)print1to10()

Output:

Printing v1 to v10:v1 = 10v2 = 20v3 = 30v4 = 40v5 = 50v6 = 60v7 = 70v8 = 80v9 = 90v10 = 100(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) "Tuple to unpack"v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 = listAPrinting v1 to v10:v1 = 1v2 = 2v3 = 3v4 = 4v5 = 5v6 = 6v7 = 7v8 = 8v9 = 9v10 = 10

Note that either locals(), globals(), or vars() can be used:

vList = []for i in range(3):vars()["v%s" % i] = i ** 2vList.append(vars()["v%s"%i])for i in range(3):print("v%s"%i, "=", vList[i])

Output:

v0 = 0v1 = 1v2 = 4

This example uses a dictionary instead of a list:

vDict = {}for i in range(3):vars()["v%s" % i] = i ** 2vDict[i] = vars()["v%s" % i]for i in range(3):print("v%s"%i, "=", vDict[i])

Output:

v0 = 0v1 = 1v2 = 4

Also note that locals(), globals(), and vars() can be used interchangeably whether creating a variable from a string, assigning a direct value, or assigning an indirect value:

vDict = {}for i in range(1000):vars()["v%s" % i] = i ** 2vDict[i] = vars()["v%s" % i]for i in range(0, 1000, 200):print("v%s"%i, "=", vDict[i])print()locals()[vDict[200]] = 1999 #indirect assignmentprint("v200 =", vDict[200], "(direct v200 value is unchanged)") print()print("v200 =", vars()[vDict[200]], "(indirect value)")print("v200 =", locals()[vDict[200]], "(indirect value)") print("v200 =", globals()[vDict[200]], "(indirect value)")print()vars()["v%s"%200] = 2020print("v200 =", globals()["v%s"%200], "(direct value)")v200 = 2021print("v200 =", locals()["v%s"%200], "(direct value)")

Output:

v0 = 0v200 = 40000v400 = 160000v600 = 360000v800 = 640000v200 = 40000 (direct v200 value is unchanged)v200 = 1999 (indirect value)v200 = 1999 (indirect value)v200 = 1999 (indirect value)v200 = 2020 (direct value)v200 = 2021 (direct value)

How it works

vDict = {}for i in range(0, 1000, 200):vars()["v%s" % i] = i ** 2vDict[i] = vars()["v%s" % i]for i in range(0, 1000, 200):print("v%s"%i, "=", vDict[i])print()# indirect assignment using 40000 as variable (variable variable)locals()[vDict[200]] = 1999 # using value 40000 as a variableprint("v200 =", vDict[200], "(direct v200 value is unchanged)") print()print("v200 =", vars()[vDict[200]], "(indirect value from key 40000)")print("{ '40000':", globals()[40000],"}")print()if vars()[vDict[200]] == globals()[40000]:print("They are equal!")if globals()[vDict[200]] == locals()[40000]:print("They are equal!")

Output:

v0 = 0v200 = 40000v400 = 160000v600 = 360000v800 = 640000v200 = 40000 (direct v200 value is unchanged)v200 = 1999 (indirect value from key 40000){ '40000': 1999 }They are equal!They are equal!