我使用Python编写了一个简单的主筛(Eratosthenes的无界筛子),但由于某种原因,它无法正常工作。这是筛子:
from itertools import count
def sieve():
nums = count(2)
while True:
n = next(nums)
nums = filter(lambda k: k%n != 0, nums)
yield n
不幸的是,这不起作用。相反,它只返回与count(2)迭代器相同的值。
为了比较,这个:
nums = count(2)
print(next(nums))
nums = filter(lambda k: k%2 != 0, nums)
print(next(nums))
nums = filter(lambda k: k%2 != 0, nums)
print(next(nums))
将打印:
2
3
5
筛选功能将打印出来:
2 3 4
我认为问题在于Python的lambda的奇怪行为,但是替换了这一行:
nums = filter(lambda k: k%n != 0, nums)
使用:
def f(k): return k%n != 0
nums = filter(f, nums)
无法解决问题。
答案 0 :(得分:7)
问题在于lambda
始终引用n
的最新值,而不是lambda
创建时使用的值。最简单的方法是使用关键字参数显式捕获值:
from itertools import count
def sieve():
nums = count(2)
while True:
n = next(nums)
nums = filter(lambda k, n=n: k%n != 0, nums)
yield n
此Python问题在well-documented StackOverflow various中为answers。公平地说,其他一些具有词汇闭包的语言也会共享相同的行为,例如JavaScript和Common Lisp。
这可能是你所说的" Python lambda"的奇怪行为。在这个问题中,虽然这种行为与lambda
无关,但是当引用一个可变变量时,闭包真正捕获了什么 - 在Python,JavaScript和Common Lisp中,它捕获变量的最新值,而在Scheme它捕获变量的值,就像创建闭包时一样。