python过滤器不起作用

时间:2016-07-22 04:35:13

标签: python lambda filter

我有一个算法可以生成素数列表作为生成器:

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

但如果我将lambda函数直接放入filter函数,如下所示:

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

我只能获得一个奇怪的列表,而不是一个主要列表。似乎filter函数不起作用。

我该怎么办?

2 个答案:

答案 0 :(得分:7)

这是一个更简单的程序,它说明了同样的问题。

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

虽然可以预期输出为3,但实际输出为6。 这是因为python中的闭包会记住变量的名称和范围,而不是创建lambda时的值。由于i在使用lambda时已被修改,因此lambda使用最新值i

你的功能也会发生同样的事情。每当修改n时,各种过滤器中的所有lambda函数也会被修改。因此,当迭代器达到9时,所有过滤器都是7的过滤因子,而不是53

因为,在您的第一种方法中,每次调用_not_divisible时都会创建一个新范围,因此该功能可以按预期工作。

如果你绝对必须直接使用lambda,你可以使用第二个参数:

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

答案 1 :(得分:4)

有效的lambda是lambda x, n=n: x%n != 0。如果您希望在定义lambda时捕获n,则显然需要执行此操作。否则,lambda只在查找变量名时才会查找lambda。在你的情况下,我认为这意味着在稍后的while循环迭代中锁定n值。