0

I was trying to code a loop generation of prime in python using filter to learn a bit about the function when I tumbled on what I believe to be a weird behavior in Python3 (not tested in other version).

Two code which, I believe, should return the same thing as they are the same code (written or in a loop). I have spend the last hour trying to understand why the second implementation does not yield the same results but can't seem to figure out why.

l = infinite()
n = next(l)
odd = filter(lambda x: (x%n != 0), l)
t = next(odd)
no3 = filter(lambda x: (x%t != 0), odd)
f = next(no3)
no5 = filter(lambda x: (x%f != 0), no3)
s = next(no5)

print(n, t, f, s)

Yields

2 3 5 7

But this code yield different results:

li = []

l = infinite()
for i in range(4):
    n = next(l)
    l = filter(lambda x: (x%n != 0), l)
    li += [n]

print(*li)
2 3 4 5

infinite() simply return all integers starting from 2 with the following code

def infinite(count = 2):
    while True:
        yield count
        count += 1

Here are some variation of that code and their results:

def _not_divisible(n):
    return lambda x: x % n != 0

li = []

l = infinite()
for i in range(4):
    n = next(l)
    l = filter(_not_divisible(n), l)
    li += [n]

print(*li)

2 3 5 7
li = []

l = infinite()
for i in range(4):
    n = next(l)
    def j(x):
        return x%n != 0
    l = filter(j, l)
    li += [n]

print(*li)
2 3 4 5

Are filters on list stored by reference and thus changing the filter at the reference affect the filtering ?

I would also really appreciate if someone can point me in a direction to understand why this execute like this as i could not find any satisfactory answer on my own.

Leyss
  • 11
  • 2
  • This is very simple, functions in python use *lexically scoped free variables*. So when you do `l = filter(lambda x: (x%n != 0), l)`, `n` is a free variable, it is *literally the same `n` from `n = next(l)`, but note, *you re-assign that `n` in the loop*. So by the time you *evaluate the filter object*, that `n` is the same for all the lambdas you created – juanpa.arrivillaga May 13 '21 at 22:52
  • Think ofit another way, you have `n = 10` then you define `def foo(x): n + x`. You then do `n = 100`, obviously then, `foo(1)` will return `101` instead of `11` The same exact thing is happening here – juanpa.arrivillaga May 13 '21 at 22:52

0 Answers0