[Tutor] Question on lists
David Ascher
da@ski.org
Thu, 18 Mar 1999 13:23:56 -0800 (Pacific Standard Time)
On Thu, 18 Mar 1999, Martijn Faassen wrote:
> Here's the improved function:
>
> from math import floor, sqrt
>
> def factor(n, a = []): # if no second argument is passed, use the
> k = floor(sqrt(n))
> for i in range(2, k+1):
> if n%i == 0:
> a.append(i) # more efficient and readable than a.insert(len(a), i)
> factor(n/i, a) # Factor quotient
> break
> return a
>
> print factor(36) # test things
Martijn should know better than to use an empty list as a default argument
-- he was probably not awake when he wrote that. Try calling factor(36) a
few times and look at the results:
>>> factor(36)
[2, 2, 3]
>>> factor(36)
[2, 2, 3, 2, 2, 3]
>>> factor(36)
[2, 2, 3, 2, 2, 3, 2, 2, 3]
>>> factor(36)
[2, 2, 3, 2, 2, 3, 2, 2, 3, 2, 2, 3]
That's because of the famous 'mutable default argument problem', discussed
in the FAQ Question 6.25 http://www.python.org/doc/FAQ.html#6.25.
The solution is to use None and do a test in the body of the function:
def factor(n, a = None):
if a is None: a = []
k = floor(sqrt(n))
for i in range(2, k+1):
if n%i == 0:
a.append(i)
factor(n/i, a)
break
return a
>>> factor(36)
[2, 2, 3]
>>> factor(36)
[2, 2, 3]
>>> factor(36)
[2, 2, 3]
>>> factor(36)
[2, 2, 3]
Note that the code *still* doesn't work (it's missing a 3), but I'll leave
that one to others. =)
--david