En Sun, 22 Mar 2009 16:42:21 -0300, R. David Murray <rdmur...@bitdance.com> escribió:
"Gabriel Genellina" <gagsl-...@yahoo.com.ar> wrote:

And if you imply that *where* you call a function does matter, it does
not. A function carries its own local namespace, its own closure, and its
global namespace. At call time, no additional "binding" is done (except
parameters -> arguments).

I poked around in the API docs and experimented with func_closure and
related attributes, and after bending my brain for a while I think I
understand this.  The actual implementation of the closure is a single
list of 'cell' objects which represent namespace slots in the nested
scopes in which the closed-over function is defined.

But the fact that it is a single list is an implementation detail, and
the implementation is in fact carefully designed so that conceptually
we can think of the closure as giving the function access to those
nested-scope namespaces in almost(*) the same sense that it has a
reference to the global and local namespaces.  That is, if what a name
in _any_ of those namespaces points to is changed, then the closed-over
function sees those changes.

In this way, we understand the original example:  when defining a
lambda having a 'free variable' (that is, one not defined in either the
local or global scope) that was a name in the surrounding function's
local namespace, the lambda is going to see any changes made by the
surrounding function with regards to what that name points to.  Thus,
the final value that the lambda uses is whatever the final value of the
for loop variable was when the surrounding function finished executing.

Exactly.

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...)

--
Gabriel Genellina

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to