Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda not work with filter [duplicate]

I tried to print all the prime number less than 100 with flowing code:

def _odd_iter():
    n=1
    while True:
        n=n+2
        yield n

def _not_divisible(n):
    return lambda x: x % n > 0    

def primes():
    yield 2
    it = _odd_iter()
    while True:
            n=next(it)
            yield n
            it = filter(_not_divisible(n),it)

for n in primes():
    if n<100:
        print(n)
    else:
        break

And it works fine. But after I change the _not_divisible function into lambda, it seems not work:

def _odd_iter():
    n=1
    while True:
        n=n+2
        yield n

def primes():
    yield 2
    it = _odd_iter()
    while True:
            n=next(it)
            yield n
            it = filter(lambda x:x%n>0,it)

for n in primes():
    if n<100:
        print(n)
    else:
        break

The result shows that the filter has dropped nothing.

Why doesn't it works with lambda?

like image 659
TJM Avatar asked Dec 04 '25 17:12

TJM


1 Answers

The problem is that the n which is used within the lambda will always refer to the local value. If n changes in the surrounding context, it will also do so within the lambda*. If you want to capture the current value, you can use this instead:

it = filter(lambda x, n=n: x % n > 0, it)

*It's probably easier to understand if you think of the context as a dictionary in which local variables are stored and looked up and which always stays the same. Explicitly written that way your primes() function would look like this:

def primes():
    ctx = {}
    yield 2
    ctx['it'] = _odd_iter()
    while True:
            ctx['n'] = next(ctx['it'])
            yield ctx['n']
            ctx['it'] = filter(lambda x: x % ctx['n'] > 0, ctx['it'])

Now it should be clear that when values in ctx change, that changes will also be picked up within the lambda. Basically the same also happens without the ctx dict, and that is what often leads to misunderstandings.

like image 141
mata Avatar answered Dec 06 '25 08:12

mata