def _odd_iter(): 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_iter() while True: n = next(it) yield n it = filter(_not_divisible(n), it) for n in primes(): if n < 1000: print(n) else: break
学到了filter,看到这个埃氏筛法求质数的程序,觉得挺有意思的。
思路如下:
1、首先得到一个从3开始的奇数iterator it
2、从iterator it中取首个数,该数为质数,第一轮即为3
3、然后运用filter,其中筛选函数为_not_divisible(n),n=3,此时it已经去除了3,现在it为从5开始的奇数iterator
4、筛选之后得到it=filter(_not_divisible(3),it)的Iterator
5、然后继续循环,n=next(it),由于是Iterator,所以要一个,算一个,取it的第一个5放入filter(_not_divisible(3),it)筛选,返回5
6、5为质数,打印5,然后继续运用filter,其中筛选函数为_not_divisible(n),n=5,此时it已经去除了5,现在it为不包含5的Iterator,filter(_not_divisible(5),filter(_not_divisible(3),it#注这里的it为最初的奇数Iterator))
7、继续循环,n=next(it),取最初奇数Iterator的下一个元素7,首先先用3除筛选,再用5除筛选,返回7,7为质数,打印7
8、然后继续运用filter,其中筛选函数为_not_divisible(n),n=7,此时it已经去除了7,现在it为不包含7的Iterator,filter(_not_dicisible(7),filter(_not_divisible(5),filter(_not_divisible(3),it#注这里的it为最初的奇数Iterator)))
8、继续循环,n=next(it),取最初奇数Iterator的下一个元素9,首先先用3除筛选,丢弃9,再取下一个元素11,依次用3、5、7除,返回11,11为质数,打印11
...继续循环下去
这里有一个问题,为什么不能把
lambda x: x % n > 0
直接放在filter中作为筛选函数呢?
def odd_iter(): n=1; while True: n+=2 yield n def choise(n): return lambda x: print('check if', x, 'is divisible by', n, 'result: ', not (x % n > 0)) or x % n > 0 def primes(): yield 2 it=odd_iter() k=0 while k<100: n=next(it) yield n it=filter(lambda x: print('check if', x, 'is divisible by', n, 'result: ', not (x % n > 0)) or x % n > 0,it) k+=1 for n in primes(): if n<1000: print(n)
输出结果如下:
2 3 check if 5 is divisible by 3 result: False 5 check if 7 is divisible by 5 result: False check if 7 is divisible by 5 result: False 7 check if 9 is divisible by 7 result: False check if 9 is divisible by 7 result: False check if 9 is divisible by 7 result: False 9 check if 11 is divisible by 9 result: False check if 11 is divisible by 9 result: False check if 11 is divisible by 9 result: False check if 11 is divisible by 9 result: False 11 check if 13 is divisible by 11 result: False check if 13 is divisible by 11 result: False check if 13 is divisible by 11 result: False check if 13 is divisible by 11 result: False check if 13 is divisible by 11 result: False 13 check if 15 is divisible by 13 result: False check if 15 is divisible by 13 result: False check if 15 is divisible by 13 result: False check if 15 is divisible by 13 result: False check if 15 is divisible by 13 result: False check if 15 is divisible by 13 result: False 15 check if 17 is divisible by 15 result: False check if 17 is divisible by 15 result: False check if 17 is divisible by 15 result: False check if 17 is divisible by 15 result: False check if 17 is divisible by 15 result: False check if 17 is divisible by 15 result: False check if 17 is divisible by 15 result: False 17 check if 19 is divisible by 17 result: False check if 19 is divisible by 17 result: False check if 19 is divisible by 17 result: False check if 19 is divisible by 17 result: False check if 19 is divisible by 17 result: False check if 19 is divisible by 17 result: False check if 19 is divisible by 17 result: False check if 19 is divisible by 17 result: False 19
因为使用匿名函数筛选时,n始终都是之前yield的那个值
这个程序关键点在于每个Iterator经过筛选,又需要再次筛选,但并不是一步到位筛选,因为不是列表,而是在next的时候进行计算,类似递归
作业如下:
回数是指从左向右读和从右向左读都是一样的数,例如12321
,909
。请利用filter()
滤掉非回数:
def is_palindrome(n): c=0 i=n while i>=1: c*=10 c+=i%10 i=int(i/10) print(c) return c==n output = filter(is_palindrome, range(1, 1000)) print(list(output))
回数还可以通过将回数变为字符串根据字符比较来判断,代码非常简洁
def is_palindrome(n): return str(n)==str(n)[::-1] output = filter(is_palindrome, range(1, 100)) print(list(output))