Changing global variables in tkinter/pmw callback

Alex Martelli aleaxit at yahoo.com
Fri Apr 6 05:28:50 EDT 2001


"Brian Elmegaard" <be at mek.dtu.dk> wrote in message
news:3ACD5CD1.5A4302E4 at mek.dtu.dk...
> Thanks, Alex.
>
> Again your pedagogical abilities clarifies python's strangeness for me.
> Not that python is strange, just that I have to understand, why it's
> not.

Glad if I have been of some help...


> > The body of this 'apply' is just re-binding a reference which
> > happens to be a local variable of this apply function.  It is,
>
> ...but this is the problem. I didn't (hmm, don't) really understand
> lambda's. Now I see how it works. The keyword arguments in the call are
> put into the local namespace, and of course they cannot be changed in
> the global then.

Excellent way to frame this.  Do remember that you never
HAVE to use lambda -- in fact, some of us think it does
not contribute much clarity in most cases.  Wherever you
would 'normally' use lambda, you can instead define a
local named-function, and pass that function-object instead
of the lambda.

Say that we want to take a list of numbers and return one where
the index value is added to each item.  One approach:

def addIndices1(alist):
    return map(lambda i,alist=alist: i+alist[i], range(len(alist)))

Now this can hardly be said to be 'lucid'... a bit better:

def addIndices2(alist):
    def addIndex(i, alist=alist):
        return i + alist[i]
    return map(addIndex, range(len(alist)))

No huge difference, but having the 'add index' primitive
explicitly named and removed from the map call does make
things a bit clearer, IMHO.


> > (Or, you could use a 'grab-bag instance object' -- it
> > does not have to be a module-object; see for example
> > http://www.activestate.com/ASPN/Python/Cookbook/Recipe/52308).
> >
>
> Still, I think I am too much of a Fortran programmer to really

I'm an old Fortran hand too, by the way -- it was my first
language, and I did a lot with it in many fields.

> understand why it is not possible to change the binding of a reference
> (correct term?) to another object just by assignment.

But it *IS* -- when you assign to a reference, you change
its binding.  The point is *this re-binding does NOT
affect other references, nor the object previously bound*;
it only affects the _reference_ itself!


> Is it due to some decisions for the implementation of python or is it
> because of some technical reasons having to do with oo-languages?

It's not really an issue of OO-ness, but, rather, of 'reference
semantics for variables' versus 'container semantics for variables'.

In several languages, such as Fortran, C++, Perl, the basic
semantic model is that a variable *CONTAINS* a value.  In those
languages, you can think of a variable as a BOX, with the value
INSIDE it.  Here, when you ASSIGN a variable to another one,
you are normally COPYING the contents: when the assignment is
done, each 'box' now holds a separate, independent copy of the
original value; what was _IN_ the variable, before something
else was assigned to it, is now 'overwritten'.  OK so far?

If a variable is a box, then clearly an object can be 'IN' one
box (variable) at a time, and modifications made to one box
have no effect on other boxes.

In other languages, such as Java, Python, Eiffel, the basic semantic
model is that a variable *REFERS TO* a value.  In those languages,
you can think of a variable as a POST-IT TAG (probably TM of
somebody or other, I guess) -- a 'label' that gets temporarily
affixed to an object.  Here, where you 'assign' a variable to
another one, you're just detaching the post-it tag from where
it was weakly-glued before, and attaching it elsewhere; when
the assignment is done, more than one post-it tag is now
attached to the _same_ object; objects are serenely unaffected
by tags being attached to, and detached from, them.

It turns out that every language DOES need _SOME_ amount of
'reference semantics' to get things done effectively.  So,
languages which start out with a 'containment' ("boxes")
semantic model end up having references AS WELL as boxes.

In Fortran (F77), this only happens on calls to functions
and subroutines; in Perl or C++, you have to use explicit
"pointers" (addresses) or "references" whenever you do need
them.  This is a very substantial complication, since TWO
semantic models must co-exist, and it leads to notorious
problems.  VERY few Fortran programmers are aware that the
following Fortran code is horribly buggy, for example:
    SUBROUTINE FOO(A, B)
    A = A + 1
    B = B + 2
    RETURN

    REAL A
    A = 0.0
    CALL FOO(X,X)
It is now, not only *completely undefined* what the value
of X may be, but even if the program is still running at
all -- by the Fortran language definition, it might have
crashed because of the forbidden aliasing, or have _ANY_
undesired and subtly buggy side effects.  As one of the few
Fortran experts around with very substantial computer science
background, I used to be called in to help debug the most
unexplainable crashes and errors, and such subtle aliasing
problems had become a weary routine -- programs which "had
always worked perfectly for 20 years" (they claimed) and
did all kind of crazy things when run on a vectorizing or
parallelizing Fortran compiler.  And C++'s problems with
references vs pointers vs copy-semantics etc etc are a
legend in their own times...!-)

[Visual Basic has its own problems in this regard -- it
uses 'boxes' for 'common, or garden' data types, but
reference-semantics for (what it calls) 'objects'; in
the end, you have to remember to use the right kind of
assignment keyword, "LET X=Y" or "SET X=Y", depending
on whether you mean assignment-as-in-boxes or else
assignment-as-in-references... *yecch*!!!]

The "boxes model of computation" is, in my opinion, the
chief culprit here.  It's a bad, sad way to think about
the progress of a computation -- maybe appropriate for
machine-language or a close kin thereof, but inevitable
source of deep complexities just as soon as 'references'
are also (inevitably!) introduced side by side with the
'boxes'.  ["boxes-and-arrows" is one name for such
complicated mixed-semantics models].

Reference-semantics is FAR simpler, because there is NO
need for 'boxes' alongsides the 'post-it tags': the
reference-semantics (post-it-tags) model of computation
is complete and self-sufficient in a way the containment
semantics (boxes) model can never be.  [boxes *CAN* be
sometimes more speedy under certain conditions -- but
they need not be, as copying data on each assignment
has its own costs -- such subtle and complicated issues
are really only appropriate for languages which *MUST*
be able to extract 100%-machine-performance at need,
such as Fortran and C++... and perhaps Eiffel, which
does, indeed, introduce an optional complication for
speed purposes to its basic, simple reference model].

People who come from a 'boxes' background (Fortran,
Pascal, C++, Basic) often do have problems in their
understanding of languages with a 'post-it tags'
paradigm (Java, Eiffel, Python) -- but the latter is
really refreshing in its utter simplicity, total
regularity, and self-sufficient completeness; and
Python adopts it integrally and without compromises,
achieving a level of simplicity that is non-pareil.


Alex






More information about the Python-list mailing list