Reputation: 23821
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,
Upvotes: 12
Views: 59243
Reputation: 373
# Python 3.8.2 (default, Feb 26 2020, 02:56:10)
glo = globals()
listB=[]
for i in range(1,11):
glo["v%s" % i] = i * 10
listB.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 = 10
v2 = 20
v3 = 30
v4 = 40
v5 = 50
v6 = 60
v7 = 70
v8 = 80
v9 = 90
v10 = 100
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) "Tuple to unpack"
v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 = listA
Printing v1 to v10:
v1 = 1
v2 = 2
v3 = 3
v4 = 4
v5 = 5
v6 = 6
v7 = 7
v8 = 8
v9 = 9
v10 = 10
vList = []
for i in range(3):
vars()["v%s" % i] = i ** 2
vList.append(vars()["v%s"%i])
for i in range(3):
print("v%s"%i, "=", vList[i])
Output:
v0 = 0
v1 = 1
v2 = 4
vDict = {}
for i in range(3):
vars()["v%s" % i] = i ** 2
vDict[i] = vars()["v%s" % i]
for i in range(3):
print("v%s"%i, "=", vDict[i])
Output:
v0 = 0
v1 = 1
v2 = 4
vDict = {}
for i in range(1000):
vars()["v%s" % i] = i ** 2
vDict[i] = vars()["v%s" % i]
for i in range(0, 1000, 200):
print("v%s"%i, "=", vDict[i])
print()
locals()[vDict[200]] = 1999 #indirect assignment
print("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] = 2020
print("v200 =", globals()["v%s"%200], "(direct value)")
v200 = 2021
print("v200 =", locals()["v%s"%200], "(direct value)")
Output:
v0 = 0
v200 = 40000
v400 = 160000
v600 = 360000
v800 = 640000
v200 = 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)
vDict = {}
for i in range(0, 1000, 200):
vars()["v%s" % i] = i ** 2
vDict[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 variable
print("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 = 0
v200 = 40000
v400 = 160000
v600 = 360000
v800 = 640000
v200 = 40000 (direct v200 value is unchanged)
v200 = 1999 (indirect value from key 40000)
{ '40000': 1999 }
They are equal!
They are equal!
Upvotes: 0
Reputation: 6684
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)]
>>> v1
0
>>> v2
1
>>> v3
2
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))}
Upvotes: 4
Reputation: 5544
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
Upvotes: 1
Reputation:
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] # 0
print v[1] # 1
print 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
Upvotes: 6
Reputation: 18870
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)
Upvotes: 9