Python bug with [] as default value in functions?
Chris Gonnerman
chris.gonnerman at usa.net
Thu Apr 12 09:00:25 EDT 2001
----- Original Message -----
From: "Dinu Gherman" <gherman at darwin.in-berlin.de>
Subject: Python bug with [] as default value in functions?
> Hi,
>
> I noticed a very strange behaviour: I've got a recursive func-
> tion like this:
>
> foo(spam, eggs=[]):
> ...
> return foo(spam, eggs=eggs)
> # the following is the same:
> # return foo(spam, eggs)
The problem is deceptively simple: The list given in the function
definition is the SAME LIST each time you call the function. If you
are familiar with C, think "static variable" and you'll get what I
mean.
The list contains the results of the first top-level call when the
second top-level call is made (instead of being empty).
> where the default argument for eggs, the empty list, is *empty*
> for the top-level call *only* when it is explicitly provided
> with the function call like this:
>
> bar = foo(mySpam, eggs=[])
>
> I've attached a longer example showing, I hope, rather pre-
> cisely what I mean.
>
> Is this a bug (I'm using Win2K, Py 2.0) or just a lack of un-
> derstanding of recursion and name spaces, delicate as they
> are, in my brain (which is not entirely excluded today...)??
>
> Regards,
>
> Dinu
>
> --
> Dinu C. Gherman
> ReportLab Consultant - http://www.reportlab.com
> .................................................................
> "The only possible values [for quality] are 'excellent' and 'in-
> sanely excellent', depending on whether lives are at stake or
> not. Otherwise you don't enjoy your work, you don't work well,
> and the project goes down the drain."
> (Kent Beck, "Extreme Programming Explained")
----------------------------------------------------------------------------
----
> """
> A test script indicating that empty lists as default values
> for function arguments might not work as they should.
>
> The default value [] is not used as defined in the function
> signature, except when the function is called indicating this
> very value explicitely.
>
> The functions used compute recursively a list of integers
> with a sum less than or equal to some given maximum value.
>
> Found on Python 2.0/Win2K.
>
> Dinu Gherman
> """
>
> from operator import add
>
>
> # [] as default value for L does not seem to work properly!!!
>
> def maxNumList1(Max, L=[]):
> """Find list of consecutive numbers n_i, where sum(n_i) < Max.
>
> This function computes recursively a list of ordered integers
> n_i, i = 0...m, starting at n_0 = 0, with n_i+1 = n_i + 1
> and sum(n_i) <= Max.
>
> E.g.
> maxNumList1(0) = [0]
> maxNumList1(1) = [0, 1]
> ..
> maxNumList1(4) = [0, 1, 2]
> ..
> maxNumList1(6) = [0, 1, 2, 3]
> ..
> maxNumList1(9) = [0, 1, 2, 3]
> maxNumList1(10)= [0, 1, 2, 3, 4]
> ..
> """
>
> assert Max >= 0, "Maximum must be a positive integer."
>
> # Add initial 0 or next integer.
> if L == []:
> L.append(0)
> else:
> L.append(L[-1]+1)
>
> # Return list if maximum exceeded or recurse.
> if reduce(add, L) > Max:
> return L[:-1]
> else:
> return maxNumList1(Max, L=L)
>
>
> def maxNumList2(Max, L=None):
> "Same as maxNumList1, but uses None as default value."
>
> # Hack to fix the bug.
> if L == None:
> L = []
>
> # From here on identical to maxNumList1() - except for
> # the call to itself at the bottom.
>
> assert Max >= 0, "Maximum must be a positive integer."
>
> # Add initial 0 or next integer.
> if L == []:
> L.append(0)
> else:
> L.append(L[-1]+1)
>
> # Return list if maximum exceeded or recurse.
> if reduce(add, L) > Max:
> return L[:-1]
> else:
> return maxNumList2(Max, L=L)
>
>
> # This is only for reference purposes and does not matter
> # or affect the strange behaviour of the implementation
> # of maxNumList1().
> def maxNumList3(Max):
> "Behaves as maxNumList2, but uses no recursion."
>
> list = []
> i = 0
> while reduce(add, list, 0) <= Max:
> list.append(i)
> i = i + 1
> return list[:-1]
>
>
> def test():
> print """Testing...
> The second and third lines should show the same results.
> The first should show identical results to the second,
> but doesn't... Bug or no bug??
> """
> for i in range(11):
> n = i
> print "maxNumList1(%d) = %s" % (n, maxNumList1(n))
> print "maxNumList1(%d, L=[]) = %s" % (n, maxNumList1(n, L=[]))
> print "maxNumList2(%d) = %s" % (n, maxNumList2(n))
> ## print "maxNumList3(%d) = %s" % (n, maxNumList3(n))
> print
>
>
> if __name__ == "__main__":
> print __doc__
> test()
>
More information about the Python-list
mailing list