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))