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不相等的元素,因此才会生成如此结果。
文章连接在此处。点击打开链接
文中的代码是这样子的
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不相等的元素,因此才会生成如此结果。
相关文章推荐
- python中的lambda表达式的闭包和filter()产生的bug
- Python中的Lambda表达式 和filter()函数 Python从入门到放弃
- python3 入门 (三) 函数与lambda表达式、闭包
- 【python】lambda表达式、filter()、map()
- python3 入门 (三) 函数与lambda表达式、闭包
- 【Python笔记】Python的几个高级语法概念浅析:lambda表达式 && 闭包 && 装饰器
- Python中特殊函数和表达式 filter,map,reduce,lambda
- Python3基础 filter与lambda表达式配合 筛选出1-100之间的奇数
- python的lambda表达式 内建函数filter map reduce
- Python入门 第四天(函数式编程、map、reduce、filter、排序函数、函数返回函数、闭包、匿名函数lambda)
- 零基础入门学习Python(12):lambda表达式、filter()和map()
- Python零基础入门之八lambda的表达式和filter、map内置函数
- Python的Lambda表达式
- python中的map,filter,reduce,lambda (转)
- Python中的匿名函数: lambda表达式
- 解决大量调用Python subprocess.Popen产生的一些bug
- 【转】Python特殊语法:filter、map、reduce、lambda
- [转]Python特殊语法:filter、map、reduce、lambda
- Python filter、map、reduce、lambda
- Python特殊语法:filter、map、reduce、lambda [转]