关于Python利用埃氏筛法筛选素数中yield迭代知识的学习日记

关于Python利用埃氏筛法筛选素数中yield迭代知识的学习日记(个人学习理解,错误更新)

  • yield存在的意义
    • 生成无限个奇数的函数方法
    • 筛去已有的素数的倍数的数字,它们肯定不是素数
    • 生成动态的可删减数字的数列
    • 输出数字的函数主体
    • 代码主体
    • 为什么不先根据奇数建立一个数列?

本篇博客是在参阅 廖雪峰的filter介绍之后对yield方法产生疑问,进行研究后所做的笔记。夹杂了我对这个filter例子的理解,如果有人阅读后发现我的理解有不到位的情况,请慷慨指出。
这里是埃氏筛法

yield存在的意义

yield把原来独立的元素划分成一个可迭代的元素,本身yield相当于返回功能和迭代器功能的结合,首先,如果执行yield方法,会先设定该元素为可迭代元素,随后返回它的值,如下:

#对这个数字'2'进行yield方法
def num():
 yield 2
for i in num():
 print(i)

上述代码在python3.7中输出的值为2。
单独使用yield在’2’上如果没有将它用于迭代,yield的作用和return没有区别。
我们都知道,整数int型在python中属于不可迭代类型,如果在函数循环中,所填入的参数是一个整数n,想要使用函数不断返回一个n+2,这是不可能的

def try1():
    n=1
    while True:
     n=n+2
     return n

for x in try1():
	if x<1000:
	 print(x)

如果你运行这个函数,输出错误应该是TypeError: ‘int’ object is not iterable,提示你整数无法被迭代(‘int’ object is not iterable)但是,在把return改为yield后

def try1():
    n=1
    while True:
     n=n+2
     yield n

for x in try1():
	if x<1000:
	 print(x)

输出的应该就是3-999之间的奇数,这就证明单独一个整数并不能在参与循环的累加后保留原值继续等待下一次利用,而yield可以把它变为可迭代对象,从而重复利用它在迭代后的值,类似C语言中常量和变量的区别,变量可以改变值,而常量不行,在Python中则是单独不可迭代的变量和常量都不能用于循环迭代的函数中,而经过yield修饰返回后的值则是可以迭代循环利用的。

生成无限个奇数的函数方法

我们知道在N*中除2外的偶数都不是素数,显然构建一个无限的奇数数列能极大加快我们筛选素数的速度。那么构建奇数数列显然是一个循环迭代的过程,以整数为研究对象,yield会帮助我们

def _odd_iter():
    n = 1
    while True:
        n = n + 2
        yield n

这段代码会在被第一次调用时返回一个3作起始,在以后的多次迭代中,起始会不断变化,以满足筛数的需求。

筛去已有的素数的倍数的数字,它们肯定不是素数

def _not_divisible(n):
    return lambda x: x % n > 0

好,现在yield修饰后的n派上用场了,以n为倍数的数字因为已经有了n这个素数,它显然就不是素数了要把它去掉
lambda是一个匿名函数,它的冒号后的字段定义了在这个函数里面对变量x的操作,这段函数中即是x%n的值大于0则返回。

生成动态的可删减数字的数列

def primes():
    yield 2#因为yield和return等同,第一次调用会返回2,也就是第一个素数
    it = _odd_iter() #起始
    while True:
        n = next(it) # next最常见于迭代中,用于指向迭代器的下一个值
        #调用next后返回序列的第一个数,以它为起始建立数列
        yield n
        it = filter(_not_divisible(n), it) # 过滤掉it中不满足_not_divisible(n)条件的数字,剩下的存到it中

输出数字的函数主体

for n in primes():
    if n < 1000:
        print(n)
    else:
        break

n,即为在1000内满足条件的数字

代码主体

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

为什么不先根据奇数建立一个数列?

数列需要内存申请,如果定义了1000长度的数列例如

for x in list(range(1,1001)):
 print(x)

申请的内存就大了,而动态生成就可以减免使用,这也是c语言中使用malloc创建数组比直接申请空间好的原因

你可能感兴趣的:(关于Python利用埃氏筛法筛选素数中yield迭代知识的学习日记)