8

Is it possible to create a local variables with Python code, given only the variable's name (a string), so that subsequent calls to "'xxx' in locals()" will return True?

Here's a visual :

>>> 'iWantAVariableWithThisName' in locals()
False
>>> junkVar = 'iWantAVariableWithThisName'
>>> (...some magical code...)
>>> 'iWantAVariableWithThisName' in locals()
True

For what purpose I require this trickery is another topic entirely...

Thanks for the help.

MitchellSalad
  • 4,171
  • 8
  • 23
  • 24
  • It is warned against but it can be done in python 2.x using the exec function - but not in 3.0: http://stackoverflow.com/questions/1450275/modifying-locals-in-python – philofinfinitejest Jan 10 '12 at 06:49
  • 5
    "For what purpose I require this trickery is another topic entirely..." - and is **infinitely more important**. Ask the question that pertains to what you really want to do, not the question that pertains to how you think you want to do it. – Karl Knechtel Jan 10 '12 at 11:16
  • Karl: MitchellSalad notes in a comment below that he's using a dictionary instead- a good choice. – David Robinson Jan 10 '12 at 17:10
  • 1
    You rarely want to do this; usually a dictionary holding your 'variables' as keys is *much* more practical. – Martijn Pieters Jan 28 '14 at 21:29

3 Answers3

9

If you really want to do this, you could use exec:

print 'iWantAVariableWithThisName' in locals()
junkVar = 'iWantAVariableWithThisName'
exec(junkVar + " = 1")
print 'iWantAVariableWithThisName' in locals()

Of course, anyone will tell you how dangerous and hackish using exec is, but then so will be any implementation of this "trickery."

David Robinson
  • 77,383
  • 16
  • 167
  • 187
  • 1
    Heh. We even used very similar sentences -- even down to the use of italics! -- to indicate that the OP probably shouldn't be doing this. I guess there really should be one obvious way to (explain why you shouldn't) do it.. – DSM Jan 10 '12 at 06:46
  • Yes, but yours sets junkVar to None, and mine sets it to 1. That makes all the difference. :) +1 to yours – David Robinson Jan 10 '12 at 06:50
  • This would only work in Python 2, as it disables the locals optimisation. *Your function will run slower* when you do this. It won't work at all in Python 3. – Martijn Pieters May 26 '14 at 11:55
5

You can play games and update locals() manually, which will sometimes work, but you shouldn't. It's specifically warned against in the docs. If I had to do this, I'd probably use exec:

>>> 'iWantAVariableWithThisName' in locals()
False
>>> junkVar = 'iWantAVariableWithThisName'
>>> exec(junkVar + '= None')
>>> 'iWantAVariableWithThisName' in locals()
True
>>> print iWantAVariableWithThisName
None

But ninety-three times out of one hundred you really want to use a dictionary instead.

DSM
  • 342,061
  • 65
  • 592
  • 494
  • Thanks for the response. For this specific instance, the exec call is looking a lot more tasty than managing a dictionary, because of the huge number of variable names my code produces. Can you perhaps elaborate a little more on what you mean by exec "sometimes" working? EDIT: A dictionary will work fine. No need to elaborate. :) – MitchellSalad Jan 10 '12 at 06:52
  • What "sometimes" works is updating the locals dictionary, not using exec. For example: `locals()["myvar"] = 1`. The [docs](http://docs.python.org/library/functions.html#locals) say: "Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter." – David Robinson Jan 10 '12 at 06:56
  • 1
    @MitchellSalad: no, I meant that updating locals() -- i.e. locals()['junkVar'] = 99 -- is slightly dangerous, and anti-recommended.. exec should work, security problems notwithstanding. I'm not sure I share your tastes, though: the *more* variables I had, the more likely I'd be to wrap them into a dictionary. – DSM Jan 10 '12 at 06:57
  • 2
    If there are a huge number of variable names, that is _all the more reason_ to use a dictionary, so you're not cluttering up your namespace. What possible reason could you have to use locals? ETA: Aha- now I see you've come to the same conclusion. And I've seen that DSM continues to be my doppelganger. – David Robinson Jan 10 '12 at 06:57
  • 1
    Okay, I'm done. Clearly @DavidRobinson can channel my views perfectly on this subject. :^) – DSM Jan 10 '12 at 06:58
-2

No need to use exec, but locals()[string], or vars() or globals() also work.

test1="Inited"

if not "test1" in locals(): locals()["test1"] = "Changed"
if not "test1" in locals(): locals()["test2"] = "Changed"

print " test1= ",test1,"\n test2=",test2
Tinmarino
  • 3,693
  • 24
  • 33