【问题标题】:Problems about filter and lambda关于过滤器和 lambda 的问题
【发布时间】:2017-03-08 11:41:02
【问题描述】:

我用python写了一些代码来获取一些素数:

N = (x for x in range(2,100))

while i<50:
    n = next(N)
    print(n)
    N = filter(lambda x:x % n > 0,N)
    i = i+1

我认为它应该打印素数 2,3,5,7,11.... 但结果是 2,3,4,5,6,7... 就像过滤器不起作用一样。 我想可能是 lambda 的问题,它没有成功提供 n 的值,所以我只是将我的代码更改为这些:

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

N = (x for x in range(2,100))

i = 0
while i<50:
    n = next(N)
    print(n)
    N = filter(fil(n),N)
    i = i+1

有效。

但我仍然怀疑,所以我写了这些:

N = (x for x in range(2,100))

i = 0
while i<50:
    n = next(N)
    print(n)
    N = filter(lambda x:x % n == 0,N)
    i = i+1

刚刚将 lambda x:x % n > 0 更改为 lambda x:x % n==0。其他部分相同。这次它起作用了,给了我 2^x: 2,4,8,16,32... 过滤器起作用了。

这真的让我很困惑。如何解释/理解这一点?

【问题讨论】:

  • 旁注:N = (x for x in range(2,100)) 是编写N = iter(range(2, 100)) 的一种不必要的手动方式。后者将是 CPython 上的 C 级迭代器,前者执行字节码以生成每个值。

标签: python python-3.x


【解决方案1】:

filter 在 Python 3 上是惰性的,因此在请求下一个数字之前不会应用过滤器。当您不对谓词使用闭包范围时,您最终会使用n 的实时值,因此您正在有效地测试每个数字是否可以被前一个数字整除(也就是说,当测试 4 时,每个 @987654323 @ wrapping 正在重新检查它是否可以被 3 整除,5 被​​一遍又一遍地检查是否可以被 4 整除,等等),但事实并非如此(我强烈怀疑你的输出从未包含1,因为你原来的genexpr 没有甚至产生 1)。

对原始代码的最简单修复是在函数定义时使用默认参数绑定n,而不是在函数体中引用它,函数体在调用时在嵌套范围内查找它,得到一个活的价值。你所要做的就是改变:

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

到:

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

【讨论】:

  • 哦抱歉,不是 1,2,3...而是从 2 开始。已编辑。
  • 那么,如何解释 filter(lambda x:x % n == 0,N) 的工作原理?
  • @B.Law:完全一样。正在测试每个数字是否可以被前一个数字整除以通过测试。所以 2 次通过,然后 3 被测试(并且发现有余数,所以它被过滤掉),4 被测试(并且没有余数,通过并更改 n)并打印。 5、6、7 和 8 都经过测试(重复,由于多个 filter 包装)是否可被 4 整除,接下来通过 8。方便的是,对于 2 的幂,用前一个 2 的幂测试可整性可以防止任何东西通过,直到下一个 2 的幂;你不需要测试任何其他东西。
  • 感谢您的详细解释。我意识到我误解了过滤器的工作原理。
猜你喜欢
  • 1970-01-01
  • 2011-06-29
  • 1970-01-01
  • 2011-10-16
  • 1970-01-01
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多