Lambda forms and scoping

R. David Murray rdmurray at bitdance.com
Mon Mar 23 10:11:15 EDT 2009


"Gabriel Genellina" <gagsl-py2 at yahoo.com.ar> wrote:
> > However, I think that a Python closure is not quite the same thing as a
> > 'computer science' closure, for the same reason that people coming from a
> > language with variables-and-values as opposed to namespaces get confused
> > when dealing with Python function call semantics.  Consider:
> >
> >     http://en.wikipedia.org/wiki/Closure_(computer_science)
> >
> > That says that a closure can be used to provide a function with a private
> > set of variables that persist from one invocation to the next, so that
> > a value established in one call can be accessed in the next.  The last
> > part of that sentence is not true in Python, since any assignment inside
> > a function affects only the local (per-invocation) namespace or (given
> > a global statement) the global namespace.  A function cannot change the
> > thing pointed to by a name in the closure.  Only the outer function,
> > for whom that name is in its local namespace, can do that.
> 
> That's true in Python 2.x, but 3.x has the "nonlocal" keyword - so you can  
> modify variables in outer scopes too:
> 
> p3> z = 1
> p3> def o():
> ...   z = 2
> ...   def i():
> ...     nonlocal z
> ...     print("z in i:", z)
> ...     z = 5
> ...   print("z in o:", z)
> ...   i()
> ...   print("z in o:", z)
> ...   z=3
> ...   print("z in o at exit:", z)
> ...   return i
> ...
> p3> i=o()
> z in o: 2
> z in i: 2
> z in o: 5
> z in o at exit: 3
> p3> z
> 1
> p3> i()
> z in i: 3
> p3> i()
> z in i: 5
> 
> (Anyway I think the inability to "modify" a variable doesn't invalidate  
> the "closure" concept...)

Invalidate, no, but it does mean that the word meant something slightly
different to a Python 2.x programmer than to, say, a Scheme programmer.
We could say that a Python 2.x closure is a "read-only closure".

But now with Python 3.x we can really have fun (thank you for that info):

>>> def g():
...     def a(x):
...             nonlocal z
...             z = z + x
...     def b(x):
...             nonlocal z
...             z = z - x
...     def p():
...             print(z)
...     z = 1
...     return a, b, p
... 
>>> add, sub, pr = g()
>>> pr()
1
>>> add(10)
>>> pr()
11
>>> sub(5)
>>> pr()
6

So, as the wikipedia article says, we could, if we wanted to, use python 3
closures to reimplement objects, in a very confusing fashion :)

--
R. David Murray           http://www.bitdance.com




More information about the Python-list mailing list