Joel VanderWerf wrote:
> ...
> 
> But in Python, the inner function only has access to the _object_, not 
> to the original variable which refers to the object, and so you have to 
> "box" the value inside an object if you want to have shared references. 

No, you still don't undestand the issue properly. You're getting closer, 
but not quite there yet.

y = 0

def foo():
     global y
     x = 0
     def bar():
         print x, y
     bar()
     x = y = 1
     bar()
     x = y = 2
     bar()
     x = y = 3
     bar()
     x = y = 4
     bar()
     x = y = 5

foo()

0 0
1 1
2 2
3 3
4 4

Now just as in Ruby, 0, 1, 2, 3, 4 are separate objects. It is literally 
impossible to change their values. All you can do is change bindings TO 
the variables. So obviously "bar" is really inheriting the _bindings_ 
for x and y because it is the _bindings_ that are changing.

So what's the problem? Consider this program:

y = 0

def foo():
     x = 0
     def bar():
         print x, y
     def change(z):
         global y
         x = y = z

     change(1)
     bar()
     change(2)
     bar()
     change(3)
     bar()
     change(4)
     bar()

foo()

The output is:

0 1
0 2
0 3
0 4

This is because Python has always adopted the rule that if you assign to 
a local variable it springs into existence -- as a local. If you want to 
overwrite a global variable, you have to specifically say: "please 
overwrite this global." It prevents people from accidentally overwriting 
globals with locals.

But there is no syntax for saying: "please overwrite this intermediate 
closure variable." It would be as easy as adding a keyword 
"intermediate" or "closure". It's purely a syntactic issue.

_But_ the addition would be useless in practice because this problem 
almost never arises in real code. Its only purpose would be to answer 
Lisp and Ruby advocates who want to say that Python doesn't really have 
closures. I don't know whether Guido will ever add it for, er, closure, 
but I do know that I have _never_ _once_ needed this keyword in hundreds 
of thousands of lines of real Python code I have written. And I am thus 
going to fight my temptation to go and bug Guido to do it so that we can 
put an end to permathreads about Python's lack of closures. ;) If this 
problem ever arose in my code (which it has not) then I could work 
around it thus:

y = 0

def foo():
     x = [0]
     def bar():
         print x[0], y
     def change(z):
         global y
         x[0] = y = z

     change(1)
     bar()
     change(2)
     bar()
     change(3)
     bar()
     change(4)
     bar()

foo()

1 1
2 2
3 3
4 4

This should prove that the problem is really not deep in the Python 
interpreter or anything like that. It would be a half day's work to 
write the patch that added the "intermediate" keyword.

By the way, there was a time when Python really did lack closures but 
there was a hacky workaround. This is where the idea that Python did not 
have "real" closures became popular (because it was true). Then Python 
added closures, but left out one minor feature and the minor feature 
allowed the idea to persist even when it had ceased to be true.

  Paul Prescod