Scope confusion...

Carl Banks imbosol at vt.edu
Tue Jan 21 03:31:27 CET 2003


Kevin at Cazabon.com wrote:
> I had a perplexing problem that turned out to be a scope issue, but I still
> can't for the life of me figure out WHY it's behaving like this.  Consider
> this minimal example, and the resulting output:
> 
> ##################
> def a(list = []):
>    list.append("test")
>    return list
> 
> def b():
>    for i in range(20):
>        print a()
> 
> if __name__ == "__main__":
>    b()
> ##################
> 
> I would expect it to print "['test']" twenty times, correct?  It doesn't.
> It prints:
> 
> ['test']
> ['test', 'test']
> ['test', 'test', 'test']
> ['test', 'test', 'test', 'test']
> ['test', 'test', 'test', 'test', 'test']
> ['test', 'test', 'test', 'test', 'test', 'test']
> ['test', 'test', 'test', 'test', 'test', 'test', 'test']
> ['test', 'test', 'test', 'test', 'test', 'test', 'test', 'test']
> ... and so on.
> 
> If you modify the definition of b to this, then it works as I'd expect:
> 
> def b():
>    for i in range(20):
>        print a([])
> 
> Is there a reason for this I'm missing?  "list" should be a private variable
> for function a(), and should be initialized to an empty list each time a()
> is called, correct?
> 
> What am I missing?  (I'm using ActivePython 2.2.1 build 222)

It's not a scope issue; it's a time of evaluation issue.  The default
value is evaluated when the function is defined, not when it's
executed.  Every time the function is called without the given
argument, the parameter gets bound to the same object.

This is done for reasons of efficiency, of course.  (Although ease of
implementation certainly had something to do with it.)  Most default
parameters are integers or strings--and we don't to create a new
object each time the function is called without the default.



-- 
CARL BANKS




More information about the Python-list mailing list