Yesterday, I made a Sieve of Eratosthenes to generate prime numbers and ran into a little weirdness that I can't really figure out.
My original code looked like this:
def generate(n, p=2, primes=[2], composites=set()):
numbers = [i for i in range(p + 1, n + 1) if i % 2 != 0]
composites = composites.union({p * i for i in range(p ** 2, n)})
for i in numbers:
if i > p and i not in composites:
primes.append(i)
return generate(n, i, primes, composites)
else:
return primes
But, with successive calls, this happens:
>>> generate(5)
[2, 3, 5]
>>> generate(5)
[2, 3, 5, 3, 5]
>>> generate(5)
[2, 3, 5, 3, 5, 3, 5]
>>> generate(5)
[2, 3, 5, 3, 5, 3, 5, 3, 5]
So it adds [3, 5] every call. It appears that the 'primes' list is in scope after successive calls to the generate function.
I fixed it by passing a copy of the list when the function recurses.
if i > p and i not in composites:
return generate(n, i, primes + [i], composites)
Anybody know what is happening here?