Python之路—Day9

迭代器与生成器

生成器(generator)


先来了解一下列表生成器:

1 list = [i*2 for i in range(10)]   
2 print(list)
>>>>
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

gen1 = (i*2 for i in range(10))
print(gen1)
>>>>>
<generator object <genexpr> at 0x0000022419B21AF0>  #列表生成器打印出来只是一个内存地址

要注意的是:

1.打印生成器,只是打印其内存地址,生成器只有在调用的时候,才会产生元素,只能一个个取值

2.生成器不能像列表一样访问某个元素,或者切片。只能通过for循环打印出来,或者通过 【__next__()】,括号里不能给参数  2.7里 是 next()

3.生成器只有一个 __next__() 方法,生成器只会记住当前的取值,可以用next方法调用下一个,但是不能往前

用函数生成生成器,以斐波那契数列进行距离

 1 def fibo(max):
 2     n,a,b = 0,0,1
 3     while n<max:
 4         #print(b)
 5         yield  b       #生成器的创建    yield:保持当前状态并中断函数,下次运行时,从这里往后运行,因为保存了当前状态
 6         a,b = b,a+b    #相当于 t =(b,a+b)   a = t[0]  b = [t1]
 7         n +=1
 8     return 'done'
 9 
10 f = fibo(10)
11 print(f.__next__())
12 print(f.__next__())
13 print('----做点别的事情----')   #生成器可以调用一下,然后停下来做别的事,其他函数会一口气打印出所有结果
14 print(f.__next__())
15 print(f.__next__())
16 print('----开始for循环----')   #__next__方法只记录当前位置
17 for i in f:
18     print(i)
19 
20 >>>>>#结果如下所示
21 1
22 1
23 ----做点别的事情----
24 2
25 3
26 ----开始for循环----
27 5
28 8
29 13
30 21
31 34
32 55
StopIteration异常:
def fibo(max):
    n,a,b = 0,0,1
    while n<max:
        #print(b)
        yield  b
        a,b = b,a+b    #相当于 t =(b,a+b)   a = t[0]  b = [t1]
        n +=1
    return '----done----'

f = fibo(3)             #只运行3次斐波那契数列
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())   #此时调用了4次next方法  ,此时会报 StopIteration错误

>>>>>> Traceback (most recent call last): 1 File "C:/Users/15302/PycharmProjects/GKXXX/day3/斐波那契数列.py", line 20, in <module> 1 print(f.__next__()) 2 StopIteration: ----done---- #这个done是函数返回值

可以用【try—except】来抓住异常(for循环用的就是这种机制)

def fibo(max):
    ‘--snip--’

f = fibo(5)
while True:                #用 try—except 来抓住异常
    try:
        x = next(f)
        print('斐波那契数列:',x)   #打印每次运行generator的值
    except StopIteration as e:  #抓住StopIteration异常
        print('Generator return value:',e.value)  #输出返回值
        break

>>>>>
斐波那契数列: 1
斐波那契数列: 1
斐波那契数列: 2
斐波那契数列: 3
斐波那契数列: 5
Generator return value: ----done----

猜你喜欢

转载自www.cnblogs.com/gkx0731/p/9460055.html