迭代器和生成器

可迭代对象

可以被for循环迭代的对象为可迭代对象(Iterable)

可以使用isinstance()判断一个对象是否是Iterable对象:

>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False

迭代器
迭代器是一个可以记住遍历的位置的对象。

迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

迭代器有两个基本的方法:iter() 和 next()。

i = iter('asd')

next(i)
>>>'a'

next(i)
>>>'s'

next(i)
>>>'d'

next(i)

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

StopIteration

当序列遍历完时,将抛出一个StopIteration(停止迭代)异常。

迭代器优点
1、“流式”数据处理方式*少内存消耗,节省内存空间
2、很方便使用,且只能取所有的数据取一次

迭代器的内部
可迭代对象:

对象里面包含iter()方法的实现,对象的iter函数经调用之后会返回一个迭代器,里面包含具体数据获取的实现
迭代器:

包含有next方法的实现,在正确范围内返回期待的数据以及超出范围后能够抛出StopIteration的错误停止迭代。

迭代器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

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

生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator

把list、dict、str等Iterable变成Iterator可以使用iter()函数:

一个实现了iter方法的对象是可迭代的,一个实现next方法的对象则是迭代器

生成器
生成器的本质就是迭代器

迭代器 我们知道是用来迭代可迭代对象的,而生成器是用来迭代方法的

我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。

如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。

生成器Generator:

  本质:迭代器(所以自带了iter方法和next方法,不需要我们去实现)

  特点:惰性运算,开发者自定义

1.生成器函数:
常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行。

只要有yield的关键字的函数就是生成器函数

一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于returnreturn的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。

特点

调用函数的之后函数不执行,返回一个生成器
每次调用next方法的时候会取到一个值
直到取完最后一个,在执行next会报错

生成器是特殊的迭代器
迭代器需要手动记录迭代位置
生成器使用yield自动记录迭代的位置

def fei(num):
    a = 0
    b = 1

    current_index = 0
    print('11111111111')
    while current_index < num:
        a, b = b, a + b

        current_index += 1
        yield a, b
        # yield b
        print('222222222222')


result = fei(5)
print(next(result))
print('第一次next完成')
print(next(result))
print('第二次next完成')

输出结果

11111111111
(1, 1)
第一次next完成
222222222222
(1, 2)
第二次next完成

yield from

def gen1():
    for c in 'AB':
        yield c
    for i in range(3):
        yield i

print(list(gen1()))

def gen2():
    yield from 'AB'
    yield from range(3)

print(list(gen2()))

输出结果:

['A', 'B', 0, 1, 2]
['A', 'B', 0, 1, 2]

yield的用法

yield 是一个类似 return的关键字,迭代一次遇到yield时就返回yield后面的值。重点是:下一次迭代时,从上一次迭代遇到的yield后面的代码开始执行。
简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后开始。


# 斐波那契
def func(n):
    a,b = 0,1
    while n > 0:
        yield b
        a,b = b,a+b
        n -= 1

def sum(n):
    return list(func(n))

print(sum(5))

输出的结果:

[1, 1, 2, 3, 5]
def yield_test(n):
    for i in range(n):
        yield call(i)
        print("i=",i)
    #做一些其它的事情
    print("do something.")
    print("end.")

def call(i):
    return i*2

#使用for循环
for i in yield_test(5):
    print(i,",")

输出的结果:

0 ,
i= 0
2 ,
i= 1
4 ,
i= 2
6 ,
i= 3
8 ,
i= 4
do something.
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值