Problem understanding how closures work

Tom Plunket tomas at fancy.org
Tue Dec 12 15:23:48 EST 2006


...at least, I think that I'm having a problem understanding the way
closures work.

I'm trying to define a function for an object which will take certain
objects from the parent scope at the time that function is defined.
For some reason, if I do this function definition in a loop, the
locals given by that function (is this a closure?) are changed each
iteration of the loop, whereas if the function definition is isn't
looped over, I get the behavior I desire.  Can anyone provide any
insight for me?

thanks,
-tom!

First, the output:

Test 1 doesn't work the way I would expect:
Test 4 says, "Test 0"
Test 4 says, "Test 1"
Test 4 says, "Test 2"
Test 4 says, "Test 3"
Test 4 says, "Test 4"

...but test 2 does?
Test 0 says, "Test 0"
Test 1 says, "Test 1"
Test 2 says, "Test 2"
Test 3 says, "Test 3"
Test 4 says, "Test 4"

Next, the program:

class Test:
	def __init__(self, name):
		self.name = name
		
	def DoCall(self):
		self.ExternalCall(self.name)
	
# The first test.	
def CreateTests1(count):
	tests = []
	for i in xrange(count):
		name = 'Test %d' % i
		t = Test(name)
		tests.append(t)
		
		def ExCall(text):
			print '%s says, "%s"' % (name, text)
			
		t.ExternalCall = ExCall
		
	return tests

# The second test.
def CreateTests2(count):
	tests = []
	for i in xrange(count):
		t = CreateTest(i)
		tests.append(t)
	return tests
		
def CreateTest(index):
	name = 'Test %d' % index
	t = Test(name)
	
	def ExCall(text):
		print '%s says, "%s"' % (name, text)
		
	t.ExternalCall = ExCall
	return t

print 'Test 1 doesn\'t work the way I would expect:'
for t in CreateTests1(5):
	t.DoCall()
	
print '\n...but test 2 does?'
for t in CreateTests2(5):
	t.DoCall()



More information about the Python-list mailing list