[Python-Dev] nested scopes confusion

Guido van Rossum guido@python.org
Tue, 04 Dec 2001 14:47:23 -0500


> I would have expected the following code to print
> 1, 2, ..., 9. Instead it prints 25, 25, 25, .. 25.
> 
> def functions():
>     result = []
>     for i in range(10):
>         def mth(*args): return i
>         result.append(mth)
>     i = 25
>     return result
> 
> for mth in functions():
>     print mth()
> 
> Reading PEP227, I can (barely) understand why it behaves this way.

Yes, you're out of luck.  Like in all decent languages with nested
scope, Python binds to the variable, not to its value at the time the
inner function is defined.

> How do I achieve the desired effect? Note that the default argument
> trick (def mth(i=i): ...) does not work because *args is present.

Use a class with a __call__ method:

    class mth:
	def __init__(self, i):
	    self.i = i
	def __call__(self, *args):
	    return self.i

and use:

    result.append(mth(i))

--Guido van Rossum (home page: http://www.python.org/~guido/)