Python yield示范
yield 关键词在python中不算常用。以前我只知道它的作用和return相似,就是返回一个值。并不知道它具体的用途和用法。
要理解yield,你必须知道generators(生成器)。而要知道生成器,需要了解iterables(可迭代对象)
生成器(Generators)就是迭代器的一种特殊形式,只不过它只能迭代一次。这是因为生成器不是将所有的数值存储在内存里,而是,立即生成数值。
和迭代器相似,我们可以通过使用next()来从generator中获取下一个值
顺便说说:集合数据类型,如list、tuple、dict、set、str等,这些可以用for循环的对象都是可迭代对象(Iterable)。
但list、dict、str虽然是Iterable,却不是迭代器(Iterator)。把list、dict、str等Iterable变成Iterator可以使用iter()函数。
迭代器对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。
Python的for循环本质上就是通过不断调用next()函数实现的
我们看看下面例子:
测试环境是ubuntu;
Python版本为2.7
def yield_test1():
print 'one'
yield 1
print 'two'
yield 2
print 'three'
yield 3
print 'is any thing?'
>y=yield_test()
>y.next() #第一次调用next 返回的是第一个yield,返回的是1
>one
>[out]1
>y.next() #第二次调用next 返回的是第二个yield,返回的是2
>two
>[out]2
>y.next() #第三次调用next 返回的是第三个yield,返回的是3
>three
>[out]3
>y.next() #第四次调用next,就不一样了,会报错StopIteration。因为已经没有东西可以yield了。但是注意,还是可以print 'is any thing'的。
>is any thing?
>StopIteration Traceback (most recent call last)
我的理解:yield和return的却别在于,yield是有记忆的返回东西。因为它记忆了上一次yield的值。
当一个生成器函数调用yield,生成器函数的“状态”会被冻结,所有的变量的值会被保留下来,下一行要执行的代码的位置也会被记录,直到再次调用next()。一旦next()再次被调用,生成器函数会从它上次离开的地方开始。如果永远不调用next(),yield保存的状态就被无视了。
接下来,我们运用yield在做个实例:
求出所有小于2000000的质数的和1+2+3+5+7+11+13+….
通常,我们的思路是这样for i in [所有小于2000000的质数]
sum+=i
#首先,我们定义 判断质数的方法
def is_prime(number):
if number > 1:
if number == 2:
return True
if number % 2 == 0:
return False
for current in range(3, int(math.sqrt(number) + 1), 2):
if number % current == 0:
return False
return True
return False
all_prime=[]#用一个list来装载所有的质数
for i in range(1,2000000):
if is_prime(i):
all_prime.append(i)
len(all_prime) #len看了下大概有66W个质数
sum=0
for i in all_prime:
sum+=i
这种方法也可以。只不过非常消耗资源。因为要把这么大一堆质数装载到一个容器里,这占了很多空间。
我们换成另一种方法:
def sum_prime(maxnum):
total = 0
for next_prime in get_primes(2):#质数从2开始
if next_prime < int(maxnum):
total += next_prime
else:
print(total)
return
def get_primes(number):
while True:
if is_prime(number):
yield number
number += 1
sum_prime(2000000)
这样就节省了很多资源,中间也不用管它到底是有哪些质数,我只要得出总的和,结果 就够了。