python dynamic scoping question

Bjorn Pettersen BPettersen at NAREX.com
Mon Apr 21 16:42:33 CEST 2003


> From: Grzegorz Adam Hankiewicz [mailto:gradha at titanium.sabren.com] 
> 
> On 2003-04-20, Bjorn Pettersen <BPettersen at NAREX.com> wrote:
> > > I have a question regarding scoping in python.  I wish to have
> > > some mechanism which puts variables at a function level scope
> > > into the global scope, dynamically.  I cannot alter my design.
> > 
> > Good luck, given what you're saying, as opposed to only the
> > fragment of code, you would need perfect knowledge of all
> > assignments that have dynamically happened in a program, i.e. you
> > can't find these variables by static/lexical analysis. I'm almost
> > positive there doesn't exists a language where you can perform
> > this operation in this direction unless you consider making _all_
> > variables global (dynamic scoping does something similar, but in
> > the other direction :-)
> 
> Hmmm... maybe I don't understand the terminology well, but what
> you say seems to be done with TCL's upvar/uplevel keywords, where
> you can "overwrite" variables from the global scope, or even a
> specific caller level up the stack. I think it's quite funky, and
> can keep you from redesigning many things under tight deadlines.
> Abusing it of course is bad, as many other things in life.

You're correct! God, it's been a long time since I looked at it. What
you're describing above (and described just as mystically in the TCL
manuals) is simply call by reference (in the C++ sense of the term).
Bear with the TCL syntax for a moment ('cause nobody would think of
implementing it like that unless the syntax looked relatively clear..):

1  proc f {} {
2     set a = 1
3     g a
4     puts $a
5  }
6
7  proc g {v} {
8     uplevel set v 42
9  }

Semantics:

1  def f():  
2     a = 1
3     g('a')  # note, without the $, TCL passes the string]ified
variable name
4     print a

7  def g(v): 
      _tmp = sys._getframe(1) # get calling frame
8     exec 'string2variable(v) = 42' in _tmp.f_globals, _tmp.f_locals

The C equivalent would be:

  void f() {
     int* a = malloc(sizeof(int));
     *a = 1;
     g(a)
     printf("%d\n", *a);
 }

 void g(int* v) {
    *v = 42;
 }

Notice that in a calling context the variable object (the variable
itself, not what it's pointing to) is referenced/dereferenced very
similarly...

So, this isn't particularly interesting. If I say that "uplevel set x
42" will create the variable if it doesn't exists, and "uplevel 2 set x
42" does the same to the caller's caller things become troublesome
(theoretically at least). I can't think of a formal semantics that
wouldn't severely restrict the language in other areas.. (and with no
semantics, no correctness proof of at least compiler optimizations, and
probably programs themselves).

To the OP, it seems simple, use TCL and bind variables using (the #0
getting you to globals):

  uplevel #0 set varname value

Learned something new today!

-- bjorn





More information about the Python-list mailing list