Misunderstanding about closures

Michael Geary Mike at DeleteThis.Geary.com
Mon Jun 7 06:50:10 CEST 2004


Alexander May wrote:
> When I define a function in the body of a loop, why doesn't the
> function "close" on the loop vairable?  See example below.

Hi Alex,

Your message title is correct: you're misunderstanding how closures work.
:-)

A closure doesn't save the current value that's bound to a name, it saves a
reference to the name itself. If you bind a different value to the name
later, the closure will see that new value.

In your first example, there is a single local name x that each instance of
the f closure refers to, so they all see the same value.

In the second example, each time you call the makef function, you create a
new local name x that belongs to that instance of makef. So when you create
the closures inside makef, each one sees its own value that is unrelated to
the others.

BTW, you'll see the same effect in JavaScript or any other language that
supports closures.

-Mike

> C:\Documents and Settings\Alexander May>python
> Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)] on
> win32
> Type "help", "copyright", "credits" or "license" for more information.
> >>> l=[]
> >>> for x in xrange(10):
> ...   def f():
> ...     return x
> ...   l.append(f)
> ...
> >>> l
> [<function f at 0x008E66F0>, <function f at 0x008E6AB0>, <function f at
> 0x008EC130>, <function f at 0x008EC170>, <functi
> on f at 0x008EC1B0>, <function f at 0x008EC1F0>, <function f at
0x008EC230>,
> <function f at 0x008EC270>, <function f at
> 0x008EC2B0>, <function f at 0x008EC2F0>]
> >>> for f in l:
> ...     f()
> ...
> 9
> 9
> 9
> 9
> 9
> 9
> 9
> 9
> 9
> 9
>
> On the other hand, the following works as I expected.
>
> >>> l=[]
> >>> def makef(x):
> ...   def f():
> ...     return x
> ...   return f
> ...
> >>> for x in xrange(10):
> ...   l.append(makef(x))
> ...
> >>> l
> [<function f at 0x008E6AB0>, <function f at 0x008EC330>, <function f at
> 0x008EC1F0>, <function f at 0x008EC230>, <functi
> on f at 0x008EC270>, <function f at 0x008EC2B0>, <function f at
0x008EC0F0>,
> <function f at 0x008EC370>, <function f at
> 0x008EC3B0>, <function f at 0x008EC3F0>]
> >>> for f in l:
> ...     f()
> ...
> 0
> 1
> 2
> 3
> 4
> 5
> 6
> 7
> 8
> 9
> >>>
>
>





More information about the Python-list mailing list