Local variables persist across function calls

Dave shepard.dl at gmail.com
Sat May 15 13:18:04 EDT 2010


I've been writing Python for a few years now, and tonight I ran into
something that I didn't understand. I'm hoping someone can explain
this to me. I'm writing a recursive function for generating
dictionaries with keys that consist of all permutations of a certain
set. Here's the function:

<code>
def make_perm(levels, result = {}, key = ''):
	local = key
	if levels == 1:
		for i in ['a', 'b', 'c', 'd']:
			result [local + i] = ''
	else:
		for i in ['a', 'b', 'c', 'd']:
			make_perm(levels - 1, result, local + i)
	return result
</code>

The first time I ran it, make_perm(2) does what I expected, returning
a dictionary of the form {'aa': '', 'ab':'', 'ac':'', ... }. But, if I
run make_perm(3) after that, I get a dictionary that combines the
contents of make_perm(2) with the values of make_perm(3), a dictionary
like {'aaa':'', 'aab':'', ...}. Running make_perm(2) again will return
the same result as make_perm(3) just did. It's like the local variable
is preserved across different calls to the same function. I don't
understand why this happens: "result" is not a global variable, and
accessing it outside the function generates a NameError, as it should.
After running make_perm once, printing the value of result inside the
function produces the last result returned on the first iteration.

If, however, I explicitly pass an empty dictionary into make_perm as
the second argument, the value of "result" is returned correctly. So I
have a solution to my problem, but I still don't understand why it
works. I've tried this on both Python 2.6 and Python 3.2, both in IDLE
and from the command line, and it behaves the same way. So it seems
like this is an intentional language feature, but I'm not sure exactly
why it works this way, or what's going on. Anyway, I'd appreciate it
if someone could explain this to me.



More information about the Python-list mailing list