python 生成器、迭代器

1. 生成器

1. 列表生成式

对于一个列表,如果你想要把列表的每个元素进行*2的操作,要么是使用for循环进行操作,还有就是可以使用列表生成式

for 循环:

num = [1,2,3,4,5]
num2= []
for n in num:
    n=n*2
    num2.append(n)
print(num2)

列表生成式:

num = [1,2,3,4,5]
num2 = [i * 2 for i in num]   # 对于num中的i,每个i*2,放到新的列表中
num3 = [i *2 for i in num if i<4] # 还可以加判断,对于num中的i,如果i<4,就i*2,然后放到新列表中
print(num2)
print(num3)

2. 简单的生成器

生成器,就是将列表生成式的 [] 改成 () 就行。

num = (i * 2 for i in range(1,10))
print(num)      # generator对象
print(num.__next__())  # 通过__next__()方法取值,一次取一个
print(next(num))       # 通过next()方法取值,一次取一个
for i in num:         # 通过循环遍历,获取所有值
    print(i)

3. 复杂的生成器

复杂的生成器。上面的生成器是很简单的,才能用列表生成式实现,但是如果复杂的呢,例如斐波拉契数列,就需要使用 yield 了

def fib(num):               # 带有yield关键字,是生成器
    n,a,b = 0,0,1
    while n<num:
        yield b            # 每次调用,执行到yeild就停止,相当于return b,
                            # 下一次调用__next__方法时,从yield的下一行开始执行
        a,b = b,a+b
        n+=1
    return 'done.'       '''注意,for循环遍历迭代器无法执行到这一句代码,只能通过异常处理捕获'''


f = fib(10)
print(f.__next__())
print(f.__next__())print('------------')

# 遍历迭代器的内容:方法一,无法获取返回值(因为每次for循环,遇到yield都相当于return一个值,当最后一次yield时,整个函数就通过yield结束了,无法执行下面的语句,故无法获取真正的return语句)
# for i in f:
#     print(i)

# 遍历迭代器的内容:方法二,通过捕获异常获取返回值
while True:
    try:
        x = next(f)  # 等同于 f.__next__()
        print(x)
    except StopIteration as e:  # 通过异常处理获取返回值
        print(e.value)          # e的值是return的内容
        break

3.通过yield给生成器传值

def consumer(name):
    print('%s来吃包子了!'% name)
    while True:
        baozi = yield
        print('%s包子被%s吃了!'%(baozi,name))

c = consumer('Wang')
c.__next__()   # 第一次执行迭代器,执行到yield停止,目的是执行:print('%s来吃包子了!'% name)
c.send('1个')  # 给yield传递值,并从上次停止的地方(yield处)开始执行下面的代码

4. 生成器的并行

import time
def consumer(name):
    print('%s来吃包子了!'% name)
    while True:
        baozi = yield
        print('%s包子被%s吃了!'%(baozi,name))

# c = consumer('Wang')
# c.__next__()   # 第一次执行迭代器,执行到yield停止
# c.send('1个')  # 给yield传递值,并继续上次停止的地方开始执行

def maker(name):
    A = consumer('A')
    B = consumer('B')
    next(A)   # A.__next__() ,执行生成器,遇到yield返回,目的是打印: %s来吃包子了!
    next(B)
    print('%s开始做包子了!'%name)
    for i in range(5):
        time.sleep(0.7)
        print('%s第%s笼做了10个包子!' %(name,i+1))
        A.send('5个')
        B.send('5个')

maker('C')

2. 迭代器

迭代对象: 能用for循环进行遍历的对象,都是迭代对象,可迭代的
迭代器: 凡是能用next调用的对象,才是迭代器,所以生成器是迭代器,但是迭代器不一定非得是生成器
from collections.abc import Iterable
from collections.abc import Iterator

# 判断是否可迭代
print(isinstance('aaaa',Iterable))
print(isinstance([1,2,3],Iterable))
print(isinstance({1:2,3:4},Iterable))
print(isinstance((1,2,3),Iterable))

# 判断是否是迭代器
print(isinstance('aaaa',Iterator))
print(isinstance([1,2,3],Iterator))
print(isinstance({1:2,3:4},Iterator))
print(isinstance((1,2,3),Iterator))
print(isinstance((x*1 for x in range(10)),Iterator))

# 转换成迭代器
a = iter([1,2,3,4,5])
print(next(a))
print(next(a))
原文地址:https://www.cnblogs.com/wztshine/p/11764726.html