77

Is there a way I can generate variable names in python in a loop and assign values to them? For example, if I have

prices = [5, 12, 45]

I want

price1 = 5
price2 = 12
price3 = 45

Can I do this in a loop or something instead of manually assigning price1 = prices[0], price2 = prices[1] etc.

Thank you.

EDIT

Many people suggested that I write a reason for requiring this. First, there have been times where I have thought this may be more convenient than using a list...I don't remember exactly when, but I think I have thought of using this when there are many levels of nesting. For example, if one has a list of lists of lists, defining variables in the above way may help reduce the level of nesting. Second, today I thought of this when trying to learn use of Pytables. I just came across Pytables and I saw that when defining the structure of a table, the column names and types are described in the following manner:

class TableFormat(tables.IsDescription):
    firstColumnName = StringCol(16)
    secondColumnName = StringCol(16)
    thirdColumnName = StringCol(16)

If I have 100 columns, typing the name of each column explicitly seems a lot of work. So, I wondered whether there is a way to generate these column names on the fly.

Curious2learn
  • 31,692
  • 43
  • 108
  • 125
  • 26
    Why would you want to do that? – sepp2k Oct 24 '10 at 22:40
  • 11
    Men invented lists.. so you don't have to do this. – adamJLev Oct 24 '10 at 23:45
  • This is a major code smell! What is you goal here? What are you going to do with "price94" when you've got it? – PaulMcG Oct 25 '10 at 01:47
  • 1
    is the use case something like this: you have some code that accepts some data and crunches it and the output is, e.g., some predicted value for Y? And you don't know how many predicted values you need (and t/4 how many variable assignments) because that depends on the size of the input array, which can vary). – doug Oct 25 '10 at 01:52
  • 2
    Another use case, meta-programming. https://github.com/apache/incubator-airflow creates DAGs like so, https://github.com/apache/incubator-airflow/blob/master/airflow/example_dags/example_branch_operator.py. If you want to create an up or downstream dependency, you do it by the variable name you assign. – russellpierce Sep 19 '16 at 12:27
  • For future travelers... after additional work with Airflow I've found that you can create those dependencies just as well with tasks stored in dicts or lists. You actually don't even need to store them at all since the call to the operator mutates the DAG. – russellpierce Dec 10 '18 at 17:53

6 Answers6

52

If you really want to create them on the fly you can assign to the dict that is returned by either globals() or locals() depending on what namespace you want to create them in:

globals()['somevar'] = 'someval'
print somevar  # prints 'someval'

But I wouldn't recommend doing that. In general, avoid global variables. Using locals() often just obscures what you are really doing. Instead, create your own dict and assign to it.

mydict = {}
mydict['somevar'] = 'someval'
print mydict['somevar']

Learn the python zen; run this and grok it well:

>>> import this
Alec
  • 8,529
  • 8
  • 37
  • 63
kanaka
  • 70,845
  • 23
  • 144
  • 140
  • 3
    assigning to locals() does not necessarily work, http://stackoverflow.com/questions/8028708/dynamically-set-local-variable-in-python – Sam Watkins Feb 05 '14 at 13:08
37

Though I don't see much point, here it is:

for i in xrange(0, len(prices)):
    exec("price%d = %s" % (i + 1, repr(prices[i])));
Tim Čas
  • 10,501
  • 3
  • 26
  • 32
  • 1
    What's the indentation of the generated code? And when is it generated? Can't make this to work in a Django project – Philip007 May 21 '13 at 10:41
  • Oh, you mean generating actual code as opposed to executing every separate thing? Just replace that `exec()` with a `print()` then. – Tim Čas Jun 10 '13 at 16:06
  • What is the purpose of using repr() ? – Bodhidarma May 11 '15 at 13:17
  • 4
    @Bodhidarma: See the description [in Python docs](https://docs.python.org/2/library/functions.html#repr) --- `repr()` attempts to return a value that, when passed to `eval()` (or `exec()` in this case), yields an object with the same value. In case of strings, it escapes them properly. *THAT SAID*, you should practically never use the above code (Python has a perfectly good concept for representing a bunch of variables --- lists!). – Tim Čas May 11 '15 at 13:53
  • that's very unsafe! using `exec` in a script is a big no no. – Jean-François Fabre Mar 20 '17 at 22:08
  • 1
    Note that this won't work in a function -- at least not today, can't remember if it did back in the Dark Ages. Since most Python code should probably not be at module level, it doesn't work where most code will live. – DSM Apr 03 '17 at 13:41
  • @DSM why it won't work ? – pippo1980 Dec 31 '22 at 17:26
26

On an object, you can achieve this with setattr

>>> class A(object): pass
>>> a=A()
>>> setattr(a, "hello1", 5)
>>> a.hello1
5
Stefano Borini
  • 138,652
  • 96
  • 297
  • 431
13

I got your problem , and here is my answer:

prices = [5, 12, 45]
list=['1','2','3']

for i in range(1,3):
  vars()["prices"+list[0]]=prices[0]
print ("prices[i]=" +prices[i])

so while printing:

price1 = 5 
price2 = 12
price3 = 45
Raviteja
  • 3,399
  • 23
  • 42
  • 69
Pranjay Kaparuwan
  • 881
  • 1
  • 11
  • 17
  • 4
    This does not work. – Billal Begueradj Apr 27 '17 at 12:16
  • 1
    There are multiple bugs in here, but the approach as such is not completely flawed; you *can* assign `vars()["prices"+str(i)]` and have a variable with the expected name. – tripleee Jan 30 '18 at 06:04
  • 1
    Yes, there were a few bugs, but this works: `prices = [5, 12, 45]` `list=['_a','_b','_c']` `for i in range(0,3):` `vars()["prices"+list[i]]= prices[i]` `print (prices_a)` `print (prices_b)` `print (prices_c)` – david Apr 22 '21 at 17:05
7

Another example, which is really a variation of another answer, in that it uses a dictionary too:

>>> vr={} 
... for num in range(1,4): 
...     vr[str(num)] = 5 + num
...     
>>> print vr["3"]
8
>>> 
PolyGeo
  • 1,340
  • 3
  • 26
  • 59
  • how do you modify `vr` though? your solution defeats the whole purpose. i'm scraping data off the web, with which i need to create instances of a class for each container item and the quantity of container items is unknown... like in question 2 in [this thread that i created](https://stackoverflow.com/questions/51092757/scrapy-data-flow-and-items-and-item-loaders) – oldboy Jun 29 '18 at 00:48
  • @Anthony the question that I am answering here is much more focused than what you have linked to. I have no advice to offer on that question. – PolyGeo Jun 29 '18 at 00:55
  • it's basically the same context. i was referring to the "Question #2" in that thread at the very bottom... – oldboy Jun 29 '18 at 01:32
  • But this, strictly speaking, is not a dynamic assigned variable, is just a dictionary. – Ghost Sep 28 '20 at 17:05
2

bit long, it works i guess...

prices = [5, 12, 45]
names = []
for i, _ in enumerate(prices):
    names.append("price"+str(i+1))
dict = {}
for name, price in zip(names, prices):
    dict[name] = price
for item in dict:
    print(item, "=", dict[item])
Leo Zhang
  • 29
  • 1