Reputation: 43
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
Upvotes: 4
Views: 5454
Reputation: 49803
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.
Upvotes: 1
Reputation: 881555
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.
Upvotes: 4