I have an algorithm that can generate a prime 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 put the lambda function into the filter
function directly, like 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 get only an odd list, not a prime list. It seems the filter
function doesn't work.
What can I do?
Python's filter() is a built-in function that allows you to process an iterable and extract those items that satisfy a given condition. This process is commonly known as a filtering operation.
filter() in python The filter() method filters the given sequence with the help of a function that tests each element in the sequence to be true or not. syntax: filter(function, sequence) Parameters: function: function that tests if each element of a sequence true or not.
In Python 2, filter() returns an actual list (which is not the efficient way to handle large data), so you don't need to wrap filter() in a list() call. Here are some other examples. Try it out: # lambda is used in place of a function print(filter(lambda x: x % 2 !=
The filter object is of the iterable type. It retains those elements which the function passed by returning True. We can also convert it to List or Tuple or other types using their factory functions. In this tutorial, you'll learn how to use the filter() function with different types of sequences.
Here's a simpler program which illustrates the same problem.
adders = []
for i in range(4):
adders.append(lambda a: i + a)
print(adders[0](3))
While one would expect the output to be 3
, the actual output is 6
.
This is because a closure in python remembers the name and scope of a variable rather than it's value when the lambda was created. Since, i
has been modified by the time the lambda is used, the lambda uses the latest value of i
.
The same thing happens in your function. Whenever n
is modified, all the lambda functions in the various filters also get modified. So, by the time the iterator reaches 9
, all the filters are filtering factors of 7
, not 5
or 3
.
Since, in your first approach you are creating a new scope with each call to _not_divisible
, the function works as intended.
If you absolutely must use a lambda directly, you can use a second argument like this:
def primes():
yield 2
L=_odd_iter()
while True:
n=next(L)
yield n
L=filter(lambda x, n=n: x%n>0, L)
The lambda that works is lambda x, n=n: x%n != 0
. You apparently need to do this if you want n
to be captured at the time the lambda is defined. Otherwise a lambda only looks up the variable name when it gets around to evaluating the lambda. In your case I think that meant locking onto an n
value in a later iteration of the while loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With