Converting functions

Peter Otten __peter__ at web.de
Mon Jan 24 04:50:46 EST 2011


iu2 wrote:

> I thought a function definition creates a closure around all used
> vars.
> As I understand now only variables that are passed as function
> arguments can participate in a closure.

No, it's just that all closures see the value of a variable at the time when 
the closure is run, not when it's defined.

I don't know how to express it more clearly, so here's another example:

>>> def f():
...     def g(): return a * a
...     def h(): return a + a
...     a = 5
...     return g, h
...
>>> g, h = f()
>>> g(), h()
(25, 10)

As you can see the local variable is not yet set when g() and h() are 
defined; but only the value by the time they are invoked matters.

Here's a more involved generator version where the value may change between 
invocations:

>>> def f(items):
...     def g(): return a * a
...     def h(): return a + a
...     yield g, h
...     for a in items:
...             yield a
...
>>> ff = f([2,3,4])
>>> g, h = next(ff)
>>> g()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in g
NameError: free variable 'a' referenced before assignment in enclosing scope
>>> next(ff)
2
>>> g(), h()
(4, 4)
>>> next(ff)
3
>>> g(), h()
(9, 6)

I think this behaviour is also called "late binding".

Peter



More information about the Python-list mailing list