生成器、迭代器详解

Jupyter notebook 模式

总结

  • Iterable:凡是可以作用于for循环的对象都是Iterable(可迭代的)。
  • Iterator:凡是可以作用于next()函数额对象都是Iterator(迭代器)对象。
  • list、tuple、dict、str、set等都是Iterable(可迭代的),因为可以使用for循环遍历,但是它们不是Iterator(迭代器),因为不能使用next()函数。
  • 生成器是一种迭代器。
  • 带有yield的函数不再是一个普通的函数,而是一个生成器generator,可用于迭代。
  • 生成器有两个方法:send()和next(),区别就在于send可传递参数给yield表达式,传递的参数会作为yield表达式的值,而yield的参数是返回给调用者的值,也就是说send可以强行修改上一个yield表达式值。send()和next()都有返回值,他们的返回值是当前迭代遇到的yield的时候,yield后面表达式的值,其实就是当前迭代yield后面的参数。
  • 通俗理解,yield会将生成器函数挂起,保存相关的状态信息,并返回一个值给调用者;next()会重新唤醒生成器函数,并从上一次挂起的位置继续执行。

1、生成器

  • 定义: 在python中,一边做循环,一边计算的机制称为生成器(generator)
  • 好处: 使用生成器可以【节约内存】,python在使用生成器时对延迟操作提供了支持。所谓的延迟是指,在需要的时候才会产生结果,而不是立即产生结果存储在内存之中。
  • 创建生成器有两种方式:一种是使用类似于列表生成式的方式,只不过把方括号换为圆括号;另外一种是使用生成器函数,在函数定义的时候引入yield语句。

1.1、列表生成式

'''有一个列表,需要将每个元素值加上10'''
alist = [0,1,2,3,4,5]
new_list = [i+10 for i in alist]    #使用列表生成式
new_list
[10, 11, 12, 13, 14, 15]
'''使用列表生成式创建一个列表'''
alist = [x**2 for x in range(5)]
alist
[0, 1, 4, 9, 16]

1.2、生成器表达式创建生成器

gen = (x**2 for x in range(5))
gen
<generator object <genexpr> at 0x059F7B10>
next(gen)
0
next(gen)
1
for x in gen:
    print(x)
4
9
16
  • 当没有元素时就会抛出StopIteration的错误。
next(gen)
---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

<ipython-input-12-6e72e47198db> in <module>()
----> 1 next(gen)


StopIteration: 

1.3、生成器函数创建生成器

  • 在有些时候生成器表达式无法实现一些复杂的功能,此时可以使用 生成器函数。
  • 下面使用**【斐波那契数列】**来解释:
'''普通函数'''
def fib(max):
    n,a,b = 0,0,1
    while n<max:
        a,b = b, a+b
        print(a,end=' ')
        n += 1
    return "done"
a = fib(5)
1 1 2 3 5 
fib(5)
1 1 2 3 5 




'done'
'''使用生成器'''
def fib(max):
    n,a,b = 0,0,1
    while n < max:
        a,b = b, a+b
        yield a
        n += 1
    return 'done'
a = fib(10)
a
<generator object fib at 0x00AEEE10>
a.__next__()
1
for i in a:
    print(i,end=' ')
1 2 3 5 8 13 21 34 55 
  • 但是上面的程序还有一点小问题:“done”哪去了?怎么打印出来?
  • 我们可以使用异常捕获机制:
Fib = fib(10)
while True:
    try:
        x = next(Fib)
        print(x,end=' ')
    except StopIteration as e:
        print("\n生成器的返回值: ", e.value)
        break
        
1 1 2 3 5 8 13 21 34 55 
生成器的返回值:  done

2、迭代器

2.1、可迭代对象(Iterable)

  • 可迭代对象主要有两种:1、集合数据类型(list、tuple、dict、set、str等);2、生成器对象

2.2、如何判读是否为Iterable?

  • 可以使用collections中的Iterable模块
from collections import Iterable
List = [1,2,3]
Tuple = (1,2,3)
Str = "123"
Dict = {0:1,1:10,2:100}
Set = set([1,2,3]) # Set = {1,2,3}
objs = [List,Tuple,Str,Dict,Set]
for obj in objs:
    print("{} is Iterable:{} ".format(obj,isinstance(obj, Iterable)))
[1, 2, 3] is Iterable:True 
(1, 2, 3) is Iterable:True 
123 is Iterable:True 
{0: 1, 1: 10, 2: 100} is Iterable:True 
{1, 2, 3} is Iterable:True 

2.3、迭代器(Iterator)

  • 可以使用next()调用并不断返回下一个值得对象称为迭代器。生成器是迭代器的子类。注意集合类型的数据不是迭代器
from collections import Iterator
for obj in objs:
    print("{} is Iterable:{} ".format(obj,isinstance(obj, Iterator)))
[1, 2, 3] is Iterable:False 
(1, 2, 3) is Iterable:False 
123 is Iterable:False 
{0: 1, 1: 10, 2: 100} is Iterable:False 
{1, 2, 3} is Iterable:False 
  • 可以使用iter()函数将上述的集合数据转换为迭代器:
for obj in objs:
    print("{} is Iterable:{} ".format(obj,isinstance(iter(obj), Iterator)))
[1, 2, 3] is Iterable:True 
(1, 2, 3) is Iterable:True 
123 is Iterable:True 
{0: 1, 1: 10, 2: 100} is Iterable:True 
{1, 2, 3} is Iterable:True 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值