2

In some other programming languages I am used to, there was a way to dynamically create and call variables. How to do this in Python?

For example let's suppose variables called test1; test2 etc. up to test9, and I want to call them like this:

for n in range(1,10):
    print concatenate('test', n)

Of course, the function concatenate is the one I am looking for.

What is the command to combine strings, integers and regular expressions in this way?


My example was a bad one, that made some of the answers suggest dictionary, or some other similar methods. It's either I am not too confident with them, or I can't use them in all cases. Here's another example:

Let's suppose we have a table of 4 rows and 4 columns, and the table has some numbers in it. I want to do some special mathematical operations, which has the row number, column number and the variable as inputs, and it outputs another row-column pair for another mathematical operation.

Logic suggests me that te easiest way to do this would be to have 16 variables, having row and column number in their names. And if I could do operations with the names of the variables, and also return the result and call it as another varialbe, the problem would be easy.

What about this context?

  • The closest thing is `getattr`, but 9 times out of 10 when people actually try to do this what they actually needed was just a `dict` – wim Jul 14 '14 at 20:08
  • Just curious, what programming languages do you know of that allow this? – arshajii Jul 14 '14 at 20:08
  • 3
    You don't, you [keep data out of your variable names](http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html) and use a collection (list or dict depending on circumstances). –  Jul 14 '14 at 20:23
  • @delnan so to be clear: the consensus seems to be that the OP wants to do a Bad Thing and we should tell him to do something else entirely. – TheSoundDefense Jul 14 '14 at 20:29
  • @TheSoundDefense exactly :) – wim Jul 14 '14 at 20:34
  • @TheSoundDefense - The advice does seem to solve the OP's intent more elegantly. I think if the up-voted answers acknowledged exec/eval as functional alternatives, however as very risky/hacky approaches, then it would be a better warning to future devs looking at this question as to why those options aren't recommended. As it stands, only devs reading through comments will see the warnings against exec/eval, while I'd think the better answers would wish to make the warning more explicit. – DreadPirateShawn Jul 14 '14 at 20:38
  • @DreadPirateShawn I don't want to spam the comment section any more, but I'd be happy to explain my rationale some more in [python chat](http://chat.stackoverflow.com/rooms/6/python) – Lukas Graf Jul 14 '14 at 20:40
  • I know dictionaries, but they are not as flexible as changing variable names can be. –  Jul 15 '14 at 10:13
  • @Ezze: you are swimming upstream if you try to use variable variable names. Dictionaries are exactly as flexible as variable variable names, you just have to use square brackets. Python has no mechanism for putting data into the name of a variable, so the ways to do it are awkward and ugly. Use a dictionary. – Ned Batchelder Jul 15 '14 at 11:12

4 Answers4

4

What you think you want is this:

>>> test1 = 'spam'
>>> test2 = 'eggs'
>>> for i in [1, 2]:
...     print locals()['test' + str(i)]
... 
spam
eggs

But what you really want is this:

>>> values = 'spam', 'eggs'
>>> my_namespace = {'test' + str(i): v for i, v in enumerate(values, 1)}
>>> for k, v in sorted(my_namespace.items()):
...     print v
... 
spam
eggs

Keep data out of your variable names.

wim
  • 338,267
  • 99
  • 616
  • 750
  • Removing my answer in light of this one. Answering the literal question, and addressing the actual problem with the proper solution. – Lukas Graf Jul 14 '14 at 20:23
  • 1
    Warning: You may be tempted to use `exec` / `eval` for this situation, if you're reading this answer. Here's elaboration on why that approach should be avoided: http://stackoverflow.com/questions/1933451/why-should-exec-and-eval-be-avoided – DreadPirateShawn Jul 14 '14 at 20:55
  • I just wish I could understand it. – Arkham Angel Nov 23 '21 at 23:28
4

You could use globals, which returns a dictionary of what is in the global scope:

>>> test1 = 'a'
>>> test2 = 'b'
>>> test3 = 'c'
>>> globals()
{'test1': 'a', 'test3': 'c', 'test2': 'b', '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, '__name__': '__main__', '__doc__': None}
>>> for n in range(1, 4):
...     print globals()["test" + str(n)]  # Dynamically access variables
...
a
b
c
>>> for n in range(1, 4):
...     globals()["dynamic" + str(n)] = n  # Dynamically create variables
...
>>> dynamic1
1
>>> dynamic2
2
>>> dynamic3
3
>>>

However, I do not recommend that you actually do this. It is ugly, hackish, and really just a bad practice.


It would be much better to do away with your numbered variables and instead use a list, which will automatically number its items by index:

>>> lst = ['a', 'b', 'c']
>>> lst[0]  # Equivalent to test1
'a'
>>> lst[1]  # Equivalent to test2
'b'
>>> lst[2]  # Equivalent to test3
'c'
>>> for i in lst:  # You can iterate directly over the list too
...     print i
...
a
b
c
>>> lst.append('d') # "Creating" a new object is easy and clean
>>> lst
['a', 'b', 'c', 'd']
>>>

Basically, instead of test1, test2, test3...you now have lst[0], lst[1], lst[2]...

  • Note that `locals()` won't actually work, as explained in the documentation you linked, because Python is under no obligation to pay any attention to the changes. Try it in a function, for examples. – DSM Jul 14 '14 at 20:51
  • @DSM - Huh, so it does. I wouldn't know because I _never_ use it like that. :P Thanks for the tip though. –  Jul 14 '14 at 20:56
-3

Python doesn't do that as well as some languages, I don't think, but they have a couple useful functions. eval() lets you evaluate a string as if it were a statement or variable, printing out the value of a given statement.

https://docs.python.org/2/library/functions.html#eval

>>> test9 = 5
>>> eval("test9")
5

for n in range(10):
  eval("test" + str(n))  # Need to convert ints to strings to make string concatenation work.

If you wanted to assign values to variables, you'd use exec().

https://docs.python.org/2/reference/simple_stmts.html#exec

>>> test9 = 6
>>> exec("test9 = 7")
>>> print test9
7
TheSoundDefense
  • 6,753
  • 1
  • 30
  • 42
  • Whoever is serially voting down the `exec` and `eval` answers, can you explain why those are undesirable? – TheSoundDefense Jul 14 '14 at 20:19
  • 2
    Sure. They are dangerous as they might execute arbitrary code, lead to unintended side effects, and are *the wrong tool for the job* if the goal is to look up a name in either local or global namespace. – Lukas Graf Jul 14 '14 at 20:21
  • Riskiness is understood, but the OP's goal (as stated, at least) also includes a way to "dynamically create" variables -- is there a preferred alternative to `exec` for this? "Be careful" is a fine disclaimer, but I'd think an answer that addresses the full question would be most appropriate. – DreadPirateShawn Jul 14 '14 at 20:24
  • 1
    @DreadPirateShawn you can write to `globals()` just fine ([`locals()`](https://docs.python.org/2/library/functions.html#locals) is a different story). Though you really don't want to do that either, that's the whole point here in my opinion - and @wim's answer addresses that nicely - just set up a local namespace. – Lukas Graf Jul 14 '14 at 20:26
  • For me the issue is not so much that it's "dangerous" or any of that hearsay (it's not really dangerous when you have 100% control over the input strings), it's just that it is a hacky and crap way to handle the problem. – wim Jul 14 '14 at 20:30
  • @wim even if we're not talking about untrusted user input, if you yourself feed the wrong thing (because of a simple mistake) to `exec` your code can wreak havoc. – Lukas Graf Jul 14 '14 at 20:35
  • The OP thinks he wants dynamic variables. He doesn't. He wants a dictionary. – Ned Batchelder Jul 15 '14 at 02:16
-4

Simply:

    print "test" + n

or

    print("test" + n);
user3324343
  • 177
  • 1
  • 3
  • 9
  • They don't want to print the string literal `testn` they want to print the value bound to the variable name `testn` – wim Jul 14 '14 at 20:10