本文目的
解释yield关键字到底是什么,为什么它是有用的,以及如何来使用它。
协程与子例程
我们调用一个普通的Python函数时,一般是从函数的第一行代码开始执行,结束于return语句、异常或者函数结束(可以看作隐式的返回None)。一旦函数将控制权交还给调用者,就意味着全部结束。函数中做的所有工作以及保存在局部变量中的数据都将丢失。再次调用这个函数时,一切都将从头创建。
对于在计算机编程中所讨论的函数,这是很标准的流程。这样的函数只能返回一个值,不过,怎么才能创建能产生一个序列的函数呢?换句话说,这个函数需要能够“保存自己的工作”。
python中的生成器可以实现这一点。
生成器中,我们的函数并没有像通常意义那样返回。常规函数中的return隐含的意思是函数正将执行代码的控制权返回给函数被调用的地方。而"yield"的隐含意思是控制权的转移是临时和自愿的,我们的函数将来还会收回控制权。
生成器(以及yield语句)最初的引入是为了让程序员可以更简单的编写用来产生值的序列的代码。 以前,要实现类似随机数生成器的东西,需要实现一个类或者一个模块,在生成数据的同时保持对每次调用之间状态的跟踪。引入生成器之后,这变得非常简单。
为了更好的理解生成器所解决的问题,让我们来看一个例子。在了解这个例子的过程中,请始终记住我们需要解决的问题:生成值的序列。
注意:在Python之外,最简单的生成器应该是被称为协程(coroutines)的东西。在本文中,我将使用这个术语。请记住,在Python的概念中提到的协程就是生成器。Python正式的术语是生成器;协程只是便于讨论,在语言层面并没有正式定义。
例子:有趣的素数
写一个函数,输入参数是一个int的list,返回一个可以迭代的包含素数的结果。
初始代码:
1 import math 2 def get_primes1(input_list): 3 result_list = list() 4 for element in input_list: 5 if is_prime(element): 6 result_list.append(element) 7 print(result_list) 8 return result_list 9 10 # 或者更好一些的... 11 def get_primes2(input_list): 12 return (element for element in input_list if is_prime(element)) 13 14 # 下面是 is_prime 的一种实现... 15 def is_prime(number): 16 if number < 2: 17 print("请提供一个大于等于2的自然数") 18 return False 19 elif number == 2: # 2为素数 20 print("%d是素数" % number) 21 return True 22 elif number % 2 == 0: #加这一步是为了提高判断效率 23 print("%d不是素数" % number) 24 return False 25 else: 26 #for current in range(3, int(math.sqrt(number) + 1), 2): 27 for current in range(2, int(math.sqrt(number)+1)): #需要加1,因为要取到sqrt(num)的值,而不是只取到它前面的值。 28 if number % current == 0: 29 print("%d不是素数"%number) 30 return False 31 print("%d是素数" % number) 32 return True 33 34 35 #print(is_prime(17)) 36 input_list=[1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 17, 19] 37 get_primes1(input_list) 38 get_primes2(input_list) 39 # 质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数 40 # 100以内质数表 41 # 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 42 # 53 59 61 67 71 73 79 83 89 97 43 # 质数具有许多独特的性质: 44 # (1)质数p的约数只有两个:1和p。 45 # (2)初等数学基本定理:任一大于1的自然数,要么本身是质数,要么可以分解为几个质数之积,且这种分解是唯一的。 46 # (3)质数的个数是无限的。 47 # (4)质数的个数公式π(n)是不减函数。 48 # (5)若n为正整数,在n方到(n+1)方之间至少有一个质数。 49 # (6)若n为大于或等于2的正整数,在n到n!之间至少有一个质数。 50 # (7)若质数p为不超过n(n>=4)的最大质数,则。 51 # (8)所有大于10的质数中,个位数只有1,3,7,9。 52 53 # 基本判断思路: 54 # 在一般领域,对正整数n,如果用2到sqrt(n)间的所有整数去除,均无法整除,则n为质数。 55 # 质数大于等于2 不能被它本身和1以外的数整除