python生成器和迭代器

128 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天

生成器和迭代器

生成器(generator)

定义:在Python中,这种一边循环一边计算的机制,称为生成器:generator

  • 得到生成器地方式
  1. 通过列表推导式得到生成器
# 得到一个生成器
g = (x*3 for x in range(10))
print(type(g))
# 方式1:通过调用__next__()来获得下一个元素
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())    #每次调用一次出一个结果
# 方式2:通过调用自带的next()函数  系统内置函数(放的是生成器的内置对象)
print(next(g))
print(next(g))
print(next(g))         #同样的也是每次运行一次出一次结果

若调用越界了,这时就会抛出StopIteration的异常,这时我们就得用异常处理来解决该问题

g = (x*3 for x in range(10))
while True:
    try:
        print(next(g))
    except:
        print('没有更多元素了!')
        break
  1. 借助函数来得到生成器
  • 定义一个函数,函数中有yield关键字
  • 单纯调用函数接收到的结果是一个生成器的地址
  • 和上面的方法一样都是用next()来得到结果
def func():
    n = 0
    while True:
        n += 1
        yield n

next(func())
func.__next__()

在这里我们可以把yield理解为retrun()和暂停的作用(return了,但没完全retrun)

  • send方法
def gen():
    i = 0
    while i < 0:
        temp = yield i
        print(temp)
        i += 1

g = gen()
g.send(None)
print(g.send('haha'))
print(g.send('23333'))

注意:每次向生成器中传值,然后第一次调用send函数只能传None(因为第一次生成器运行时会在yield暂停,而此时传入其他值接受不了,只能传入None)

应用多任务

进程>线程>协程

image-20220421200755368.png

示例:

有一个程序员上班想摸鱼,于是协程的想法在他脑中冒出

def demo(n):
    for i in range(1,n)
    print('正在写{}段代码'.format(i))
    yield None
def music(m):
    for i in range(1,m)
    print('正在听第{}首歌'.foemat(i))
    yield None
    
n1 - demo(5)
n2 = music(5)
while True:
    try:
        new(n1)
        new(n2)
    except:
        pass

只有上面这样利用协程老板才不会发现他在摸鱼

迭代器

迭代时访问集合元素的一种方式,迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合第一个元素开始访问,知道所有元素都被访问完结束,迭代器只能往前不能往后(可迭代的定义)

可迭代的对象

  1. 生成器
  2. 元组,列表,集合,字典,字符串

如何判断是否是可迭代的

  • isinstance
from collection import Iterable

list1 = [1,2,3,4]
f = isinstance(list1,Iterable)
print(f)

注意:可迭代的 ≠ 迭代器

可以被next()函数调用并返回下一个值的对象称为迭代器:Iterator

  • 把可迭代的转变为迭代器:iter()
list = [1,2,3,4,5]
list1 = iter(list)

注意:生成器一定是迭代器,但迭代器不一定是生成器

image-20220421205141915.png