Python filter not working

I have an algorithm that can generate a primary list as a generator:

def _odd_iter(): n=3 while True: yield n n=n+2 def _not_divisible(n): return lambda x: x % n > 0 def primes(): yield 2 L=_odd_iter() while True: n=next(L) yield n L=filter(_not_divisible(n), L) x=1 for t in primes(): print(t) x=x+1 if x==10: break 

But if I included the lambda function in the filter function, as shown below:

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

I can only get an odd list, not a simple list. The filter function does not seem to work.

What can I do?

+7
python lambda filter
source share
2 answers

Here's a simpler program that illustrates the same problem.

 adders = [] for i in range(4): adders.append(lambda a: i + a) print(adders[0](3)) 

While you can expect the output to be 3 , the actual output will be 6 . This is because closing in python remembers the name and scope of the variable, not the value when the lambda was created. Since i was changed at the time of using lambda, lambda uses the last value of i .

The same thing happens in your function. Whenever n changes, all lambda functions in different filters also change. Thus, by the time the iterator reaches 9 , all filters are filtering factors 7 , not 5 or 3 .

Since in your first approach you create a new scope with every call to _not_divisible , the function works as intended.

If you absolutely must use lambda directly, you can use the second argument as follows:

 def primes(): yield 2 L=_odd_iter() while True: n=next(L) yield n L=filter(lambda x, n=n: x%n>0, L) 
+6
source share

The lambda that works is lambda x, n=n: x%n != 0 . You probably need to do this if you want n be captured during lambda definition. Otherwise, the lambda only looks for the variable name when it comes close to evaluating the lambda. In your case, I think this meant locking the value of n in a later iteration of the while loop.

+4
source share

All Articles