Day19 列表生成器、迭代器&生成器

  • 列表生成式
a=[i*2 for i in range(10)]
print(a)
>>>
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
  • 迭代器&生成器

生成器(generator):

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

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

只有在调用时才会生成相应的数据

方法一:

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

把一个列表生成式的[]改成()

a=(i*2 for i in range(10))
print(a)
>>>
<generator object <genexpr> at 0x05482570>

调用方法:a.__next()__

print(next(a))
print(next(a))
>>>
0
2

or

for i in a:
    print(i)
>>>
0
2
4
6
8
10
12
14
16
18

方法二:

斐波那契数列(Fibonacci):除第一个和第二个数外,任意一个数都可由前两个数相加得到

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'

赋值语句:

a, b = b, a + b

相当于:

t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]

将函数中print(b)改为yield b就变成了生成器

def fib(max):
    n,a,b = 0,0,1

    while n < max:
        #print(b)
        yield  b
        a,b = b,a+b

        n += 1

    return 'done'

f=fib(5)

print(f)
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
>>>
<generator object fib at 0x05792570>
1
1
2
3
for i in f:
    print(i)
>>>
1
1
2
3
5

但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIterationvalue中:

g = fib(6)
while True:
    try:
        x = next(g)
        print('g:', x)
    except StopIteration as e:
        print('Generator return value:', e.value)
        break
>>>
g: 1
g: 1
g: 2
g: 3
g: 5
Generator return value: done
  • 迭代器
 

猜你喜欢

转载自www.cnblogs.com/q1ang/p/8955243.html