4

Is there a way in Python to add to the locals name-space by calling a function without explicitly assigning variables locally?

Something like the following for example (which of course doesn't work, because locals() return a copy of the local name-space) where the print statement would print '1'.

def A():
  B(locals())
  print x

def B(d):
  d['x'] = 1
2
  • I can only ask: Why!? For the love of the Gods of Programmming WHY!? :-) Commented Oct 10, 2009 at 23:03
  • 1
    Please use assignment statement for assignment of variables. That's what it's for. Please do things the simplest, most obvious way. Please. Commented Oct 11, 2009 at 11:56

2 Answers 2

4

In Python 2.*, you can disable the normal optimizations performed by the Python compiler regarding local variable access by starting your function with exec ''; this will make the function very much slower (I just posted, earlier today, an answer showing how the local-variable optimization can easily speed code up by 3 or 4 times), but it will make your desired hack work. I.e., in Python 2.*:

def A():
  exec ''
  B(locals())
  print x

def B(d):
  d['x'] = 1

A()

will emit 1, as you desire.

This hack was disabled in Python 3.* (where exec is just a function, not a statement nor a keyword any more) -- the compiler now performs the local variable optimization unconditionally, so there is no longer any way to work around it and make such hacks work.

Sign up to request clarification or add additional context in comments.

3 Comments

Brilliant, this is completely new to me. I'm going to investigate further. However I'm not quite really looking for a hack, esp one that'll degrade performance. Alex, how would you do it if you wanted to not explicitly define a set of variables locally (say have them defined dynamically by a subroutine) but want to access them locally as if they are local variables?
@Dilan, I wouldn't -- "explicit is better than implicit" (do import this at an interactive Python prompt to see the whole text of the Zen of Python). There is no way to make local variables that isn't either explicit, or a hack.
@Dilan, you're welcome, but remember to accept answers to your questions -- not just verbally, but by using the tickmark-like icon near the answer's count of upvotes. That's fundamental SO etiquette!-)
1

Seems pretty horrible to rely on a hack like exec ''. What about communicating like this with the global statement, it seems to work:

>>> def outer():
...   global x
...   b()
...   print x
... 
>>> def b():
...   global x
...   x = 2
... 
>>> outer()
2

You could create a namespace for your variables instead:

class Namespace(object):
    pass

def A():
  names = Namespace()
  B(names)
  print names.x

def B(d):
  d.x = 1

Then use names.x or getattr(names, "x") to access the attributes.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.