free variables /cell objects question

gangesmaster tomerfiliba at gmail.com
Thu Jan 25 06:42:54 EST 2007


no, it has nothing to do with "i" being global.

>>> tuple(lambda: i for i in range(10))[0]()
9
>>> tuple(lambda: i for i in range(10))[1]()
9

what i see as a bug is this code not working as expected:

>>> def make_foos(names):
...     funcs = []
...     for n in names:
...             def foo():
...                     print "my name is", n
...             funcs.append(foo)
...     return funcs
...
>>> foos = make_foos(["hello", "world", "spam", "bacon"])
>>> foos[0]()
my name is bacon
>>> foos[1]()
my name is bacon
>>> foos[2]()
my name is bacon
>>>

i have to create yet another closure, make_foo, so that the name
is correctly bound to the object, rather than the frame's slot:

>>> def make_foo(name):
...     def foo():
...             print "my name is", name
...     return foo
...
>>> def make_foos(names):
...     return [make_foo(n) for n in names]
...
>>> foos = make_foos(["hello", "world", "spam", "bacon"])
>>> foos[0]()
my name is hello
>>> foos[1]()
my name is world
>>> foos[2]()
my name is spam


-tomer

On Jan 24, 2:46 am, "Terry Reedy" <tjre... at udel.edu> wrote:
> "gangesmaster" <tomerfil... at gmail.com> wrote in messagenews:1169563580.634000.122540 at v45g2000cwv.googlegroups.com...
> | so this is why [lambda: i for i in range(10)] will always return 9.
>
> No, it returns a list of 10 identical functions which each return the
> current (when executed) global (module) variable i. Except for names,
> 'lambda:i' abbreviates 'def f(): return i'.
>
> >>> a=[lambda: i for i in range(10)]
> >>> i=42
> >>> for j in range(10): print a[j]()42
> 42
> 42
> 42
> 42
> 42
> 42
> 42
> 42
> 42
>
> >>> for i in range(10): print a[i]()0
> 1
> 2
> 3
> 4
> 5
> 6
> 7
> 8
> 9
>
> >>> del i
> >>> for j in range(10): print a[j]()Traceback (most recent call last):
>   File "<pyshell#23>", line 1, in -toplevel-
>     for j in range(10): print a[j]()
>   File "<pyshell#8>", line 1, in <lambda>
>     a=[lambda: i for i in range(10)]
> NameError: global name 'i' is not defined
>
> | imho that's a bug, not a feature.
>
> The developers now think it a mistake to let the list comp variable 'leak'
> into the global scope.  It leads to the sort of confusion that you
> repeated.  In Py3, the leak will be plugged, so one will get an exception,
> as in the last example, unless i (or whatever) is defined outside the list
> comp.
> 
> Terry Jan Reedy




More information about the Python-list mailing list