12

Suppose I have a hierarchy of functions, I want to be able to access (not change!) the parents scope. Here is an illustrative example.

def f():
    a = 2
    b = 1
    def g():
        b = 2
        c = 1
        print globals() #contains a=1 and d=4
        print locals() #contains b=2 and c=1, but no a
        print dict(globals(), **locals()) #contains a=1, d=4 (from the globals), b=2 and c=1 (from g)
        # I want a=2 and b=1 (from f), d=4 (from globals) and no c
    g()
a = 1
d = 4
f()

Can I access f's scope from within g?

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
Andy Hayden
  • 359,921
  • 101
  • 625
  • 535

1 Answers1

9

In general, you can't in Python. If your Python implementation supports stack frames (CPython does), you could inspect the calling function's frame using the inspect module and extract the local variables, but I doubt this is the best solution for the problem you want to solve (whatever that might be). There is probabaly some flaw in your design if you think you need this.

Note that using inspect will enable you to go up in the call stack, not in the stack of lexical scopes. If you return g from f(), the scope of f will be gone, so there is no way at all to access it, since it does not even exist.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • Is it reasons of security for not being able to do this? I find scope so subtle/confusing, but the scope of `f` surely still "exists" once you call `g` from within `f`, as afterwards you go back executing to `f` (!) The reason I was thinking about this is for [unit testing for side-effects](http://stackoverflow.com/questions/11559401/testing-for-side-effects-in-python#comment15290923_11559401)... :s – Andy Hayden Jul 19 '12 at 13:16
  • 7
    @hayden: No, it's not for security reasons. As I said, you *can* go up the call stack if your Python implementation supports stack frames – just do something like `inspect.currentframe().f_back.f_locals` to get the locals of the calling frame, which will be an instance of `f` in your example. The reason you cannot access variables from a *lexical* scope is that this notion does not make sence. There can be multiple instances of `f` in the call stack, all with different locals, or there could be none at all. – Sven Marnach Jul 19 '12 at 13:21
  • 1
    The reason why you *shouldn't* be doing something like this is against the gist of a programming language with lexical scoping as opoosed to dynamic scoping (that is, practically any programming language). See http://en.wikipedia.org/wiki/Dynamic_scoping#Lexical_scoping_and_dynamic_scoping for further details. – Sven Marnach Jul 19 '12 at 13:23
  • I think what is confusing me here is that `g` **does** have access to `f`'s variables ([e.g.](https://gist.github.com/3144177))... but we just can't display them. – Andy Hayden Jul 19 '12 at 14:11
  • @hayden: `g()` does not have access to `f`'s `b`, unless you use stack frame introspsection, because it is hidden by `g`'s `b`. And once you actually close over some names of `f`, they get attached to the closure, so you could access them by introspection. But your code actually doesn't access any name from `f`, so it won't produce a closure. – Sven Marnach Jul 19 '12 at 14:16
  • Ah ha! That was the bit I was missing (that they become attached only after being looked up). If we *could* iterate over all "possible" variables, we'd be done... but we don't know what they are! :( – Andy Hayden Jul 19 '12 at 15:32
  • If you define `f_local_state = locals().keys()` in the function `f`, then, while in `g` you can iterate over `f`'s scope since you can access `f_local_state` in `g`. – AmourK Nov 13 '18 at 22:03