Categories
python variable-variables

How do I create variable variables?

498

How do I create the equivalent of PHP variable variable names in Python?

I hear this is a bad idea, in general, though. Is that true?

8

  • 72

    it’s the maintainance and debugging aspects that cause the horror. Imagine trying to find out where variable ‘foo’ changed when there’s no place in your code where you actually change ‘foo’. Imagine further that it’s someone else’s code that you have to maintain… OK, you can go to your happy place now.

    Sep 3, 2009 at 14:28

  • 16

    A further pitfall that hasn’t been mentioned so far is if such a dynamically-created variable has the same name as a variable used in your logic. You essentially open up your software as a hostage to the input it is given.

    – holdenweb

    Dec 19, 2014 at 10:50

  • 4

    You can modify your global and local variables by accessing the underlying dictionaries for them; it’s a horrible idea from a maintenance perspective … but it can be done via globals().update() and locals().update() (or by saving the dict reference from either of those and using it like any other dictionary). NOT RECOMMENDED … but you should know that it’s possible.

    Mar 19, 2020 at 9:13

  • 2

    @JimDennis actually, no it can’t. Modifications to the dict returned by locals will not affect local namespaces in CPython. Which is another reason not to do it.

    May 18, 2020 at 22:27

  • 2

    @juanpa.arrivillaga: I had tried testing this in an IPython shell, but did so at the top level (where locals() behaves like globsls()). Redoing that test within a nested code (within the definition of a function) does show that I can’t modify locals() from within that. As you say, the help for locals (3.7.6) does warn: “NOTE: Whether or not updates to this dictionary will affect name lookups in the local scope and vice-versa is implementation dependent and not covered by any backwards compatibility guarantees.”

    May 22, 2020 at 8:22


402

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

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

    108

    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

      85

      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

      • 1

        locals().update({‘new_local_var’:’some local value’}) works just fine for me in Python 3.7.6; so I’m not sure what you mean when you say you cannot assign values through it.

        Mar 19, 2020 at 9:04


      • Given x = "foo" and locals()["x"] = "bar" using print x gives the output bar for Jython 2.5.2. This was tested with an On Demand Automation Script in maximo.

        – Preacher

        Mar 30, 2020 at 22:52

      • 5

        The documentation of locals() specifically says: “The contents of this dictionary should not be modified.” (emphasis mine)

        – martineau

        Jun 23, 2021 at 21:14

      • @JimDennis`locals()“ provides a dictionary created to represent local variables. Updating it does not guarantee to update the actual local variables. In modern Python implementations it’s more like a picture (showing the content) in a nice frame (a high-level dict) – drawing on the picture won’t actually change the real thing.

        Nov 10, 2021 at 11:16

      • 1

        The reason it doesn’t work, at least on CPython, is that CPython allocates a fixed size array for locals, and the size of said array is determined when the function is defined, not when its run, and can’t be changed (access to true locals doesn’t even use the name; the name is replaced with the index into the array at function compile time). locals() returns a true dict; within a function, that dict is made by loading names and associated values in the array when you call locals(), it won’t see future changes. If it changes, you’re at global or class scope (which use dict scopes).

        Dec 2, 2021 at 16:02