生成器
在Python中,一边循环一边计算的机制,称为生成器:generator。它不会主动完成全部运行,而是在具体调用时,完成我们需要的某一步,然后停止,等待下次调用。它所蕴涵的是某种计算规则即算法,而不是像列表那样的计算结果。
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>
L作为list,而g作为generator。list中的元素可以直接使用,但generator中的元素需要调用才能生成。
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
当然也可以使用for循环获取generator中元素
# -*- coding: utf-8 -*-
"""
Created on Tue Aug 13 10:04:55 2019
@author: Administrator
"""
a=(x*x for x in range(4))
print(next(a))
print(next(a))
print(next(a))
print('~~~~~~~~~~~~')
for i in a:
print(i)
#输出
#0
#1
#4
#~~~~~~~~~~~~
#9
生成器的生成有两种方式
第一种是使用与列表生成器相似的结构:
>>> L = [x * x for x in range(4)]
>>> G = (x * x for x in range(4))
第二种则是与函数相似的结构:
def fib1(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'
def fib2(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
当函数中包含了yield后,便不是普通函数了,而是generator,在调用fib1时,会运行整个函数,直至遇到return,而在调用fib2时,首先是生成一个generator对象f=fib2(max),此时f为一个实例,当每次调用next()的时候执行f,遇到yield时返回,再次执行时从上次返回的yield语句处继续执行。
使用generator实现素数的生成
# -*- coding: utf-8 -*-
"""
Created on Thu Feb 28 20:57:18 2019
@author: Administrator
"""
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