您的位置:首页 > 编程语言 > Python开发

python中的lambda表达式的闭包和filter()产生的bug

2017-08-08 23:25 561 查看
      最近在看廖雪峰的官网学习python,看到函数式编程的filter章节那里,作者给出了一个demo是关于用filter求素数。
     文章连接在此处。点击打开链接
     文中的代码是这样子的
     filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。用filter求素数计算素数的一个方法是埃氏筛法,它的算法理解起来非常简单:首先,列出从2开始的所有自然数,构造一个序列:2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,14, 15, 16, 17, 18, 19, 20, ...取序列的第一个数2,它一定是素数,然后用2把序列的2的倍数筛掉:3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,15, 16, 17, 18, 19, 20, ...取新序列的第一个数3,它一定是素数,然后用3把序列的3的倍数筛掉:5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,17, 18, 19, 20, ...取新序列的第一个数5,然后用5把序列的5的倍数筛掉:7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,18, 19, 20, ...不断筛下去,就可以得到所有的素数。以下贴出代码def odd_iterator(): #构造一个从3开始的奇数序列,注意这是一个生成器,并且是一个无限序列。
n = 1

while True:

n = n + 2

yield n

def not_divisible(n):#筛选函数

return lambda x: x % n != 0

def primes():

yield 2

it = odd_iterator()# 初始序列

while True:

n = next(it)# 返回序列的第一个数

yield n

it = filter(not_divisible,it)# 构造新序列,<更改此处>

# 打印1000以内的素数:

for i in primes():

if i < 1000:

print(i)

else:

break

     
 
因为偷懒我把it = filter(not_divisible, it)
   更改成了这样it = filter(lambda x: x % n != 0, it)    结果就出错了,想了好久,才记得这样是因为lambda有闭包,有关闭包的事情大家可以自行百度一下,我就不在这里说了。这里我给大家一个更简单的例子体现闭包:
  #生成一个0~9的listl = [x for x in range(10)]

j = [x for x in range(10)]

def func(i):

return lambda x: x != i#筛选出与i不相同的数

for i in range(10):

j = filter(func, j)#不同处

for i in range(10):

l = filter(lambda x: x != i, l)#不同处

print(list(l))

print(list(j))


输出是[0, 1, 2, 3, 4, 5, 6, 7, 8][0, 1, 2, 3, 4, 5, 6, 7, 8, 9]       首先,按照我们的思维,程序应该生成一个[]空list,但是两个输出都不是,为什么呢?这里就关系到闭包了。    根据闭包,在for循环里,闭包只会保存循环最后一个数,也就是9。所以程序的实际生成的是筛选list里与9不相等的元素,因此才会生成如此结果。 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: