一、生成器

1. 列表生成

>>> [i*2 for i in range(10)]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>> [i for i in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


列表生产优点:节约内存,采取边生成边使用元素的模式,使用完了则销毁。而普通的列表,是一次性在内存中创建。


2. 创建第一个生成器 generator

>>> gen = (i*2 for i in range(10))   # 即把列表的[] 改成()
>>> for j in gen:
...   print(j)
...
0
2
4
6
8
10
12
14
16
18


3. next使用(__next__)

>>> gen = (i*2 for i in range(10))
>>> gen.__next__()
0
>>> gen.__next__()
2
>>> gen.__next__()
4
>>> next(gen)
6

注:如果取完了,则会报错

>>> next(gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration


4. for循环迭代

>>> gen = (i*2 for i in range(10))
>>> for i in gen:
...   print(i)
...
0
2
4
6
8
10
12
14
16
18


5. 生成器保存的是算法,通过算法计算式出下一个值,__next__()

案例:

def fib(max):
    count, a, b = 0, 0, 1    #1
    while count < max:       #2
        yield b            #3
        a, b = b, a+b      #4
        
        count = count+1    #5
g = fib(6)
print(g)    # 结果:<generator object fib at 0x0000000000731DB0>
for i in g:
    print(i)

结果:

1    #1-->2-->3    count=0
1    #4-->5--2-->3 count=1
2    #4-->5--2-->3 count=2
3    #4-->5--2-->3 count=3
5    #4-->5--2-->3 count=4
8    #4-->5--2-->3 count=5

使用while循环:

def fib(max):
    count, a, b = 0, 0, 1
    while count < max:
        yield b
        a, b = b, a+b
        count = count+1
g = fib(6)
print(g)
while True:
    try:
        print('value:', g.__next__())
    except StopIteration as e:
        print('except value:', e.value)
        break

结果:

<generator object fib at 0x0000000001F71DB0>
value: 1
value: 1
value: 2
value: 3
value: 5
value: 8
except value: None


6. 通过yield 实现并发

import time
def consumer(name):
    print('%s开始吃水果' % name)
    while True:
        fruit = yield
        print('%s吃了%s水果' % (name, fruit))
def productor():
    Sam = consumer('Sam')
    Jey = consumer('Jey')
    Sam.__next__()   # 是为了让程序走到fruit = yield,准备吃的步骤
    Jey.__next__()
    for i in range(1,4):
        time.sleep(1)
        print('开始分发水果.....')
        Sam.send(i)
        Jey.send(i)
productor()

结果:

Sam开始吃水果
Jey开始吃水果
开始分发水果.....
Sam吃了1水果
Jey吃了1水果
开始分发水果.....
Sam吃了2水果
Jey吃了2水果
开始分发水果.....
Sam吃了3水果
Jey吃了3水果


二、迭代器

1. 可迭代对象  Iterable

----> 字符串、列表、元组、字典、集合   # 不是生成器

----> 生成器,包括带yield的函数

使用isinstance判断是否可迭代对象;

>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance('ggg', Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance((i for i in range(3)), Iterable)
True


2. 迭代器的定义

可以被next()调用并不断返回下一个值,成为迭代器:Iterator

>>> from collections import Iterator
>>> isinstance([], Iterator)
False
>>> isinstance((i for i in range(3)), Iterator)
True


3. 使用iter() 把iterable 变成iterator

>>> from collections import Iterator
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('asd'), Iterator)
True