Say, I have some scope with variables, and a function called in this scope wants to change some immutable variables:
def outer(): s = 'qwerty' n = 123 modify() def modify(): s = 'abcd' n = 456
Is it possible somehow to access the outer scope? Something like nonlocal
variables from Py3k.
Sure I can do s,n = modify(s,n)
in this case, but what if I need some generic 'injection' which executes there and must be able to reassign to arbitrary variables?
I have performance in mind, so, if possible, eval
& stack frame inspection is not welcome :)
UPD: It's impossible. Period. However, there are some options how to access variables in the outer scope:
- Use globals. By the way,
func.__globals__
is a mutable dictionary ;) - Store variables in a dict/class-instance/any other mutable container
- Give variables as arguments & get them back as a tuple:
a,b,c = innerfunc(a,b,c)
- Inject other function's bytecode. This is possible with
byteplay
python module.
Your options are to use global variables,
or define those as methods and use a class or instance variable.
Define the variables outside of the functions and use the
global
keyword.Sometimes I run across code like this. A nested function modifies a mutable object instead of assigning to a
nonlocal
:This is not how
nonlocal
works. It doesn't provide dynamic scoping (which is just a huge PITA waiting to happen and even more rarely useful than your average "evil" feature). It just fixes up lexical scoping.Anyway, you can't do what you have in mind (and I would say that this is a good thing). There's not even a dirty but easy hack (and while we're at it: such hacks are not discouraged because they generally perform a bit worse!). Just forget about it and solve the real problem properly (you didn't name it, so we can't say anything on this).
The closest you could get is defining some object that carries everything you want to share and pass that around explicitly (e.g. make a class and use
self
, as suggested in another answer). But that's relatively cumbersome to do everywhere, and still hackery (albeit better than dynamic scoping, because "explicit is better than implicit").You can probably also do this (not saying it is right);
define a function that returns an array with rows like so
Then do in the scope you need the vars
this is pretty darn hacky though.