python之迭代器和生成器

来源:互联网 发布:淘宝网跑步机 编辑:程序博客网 时间:2024/05/29 02:32

1.迭代器:一个可以记住遍历位置的对象。
可以使用isinstance()判断一个对象是否是Iterable对象:

from collections import Iterableisinstance([],Iterable)

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

from collections import Iteratorisinstance([],Iterator)

这里写图片描述
a.迭代器两个基本方法:iter(),next()方法。
内置函数iter(iterable),表示把可迭代对象变成迭代器(iterator)。调用(对象.__iter__())。
内置函数next(iterator),表示查看下一次迭代的值(iterator.__next__()

it = iter([1,2,3,4])#创建迭代器对象while True:    try:        x = next(it)#获取下一个值        print(x)    except StopIteration:        #遇到StopIteration就退出循环        break

b.迭代器协议:对象必须提供一个next()方法,执行该方法返回迭代中的下一项,要么引起一个Stopiteration异常,终止迭代。
python中的for循环
循环所有的对象,全部是使用迭代器协议。
(字符串,列表,元组,字典,集合,文件对象),这些都不是可迭代对象,只不过在for循环中,调用了它们内部的__iter__方法,把它们变成了可迭代对象。然后for循环调用可迭代对象的__next__()方法去找,然后for循环会自动捕捉StopIteration异常,来终止循环。

L = [1,2,3,4]for i in L:#for循环调用可迭代对象的__next__()去取值,    print(i)#而且for循环会捕捉StopIteration异常,以终止对象。

这里写图片描述

迭代器总结:
a.可作用于for循环对象本身都是iterable(可迭代对象)类型,或者对象本身有obj.iter方法也是iterable.
b.凡是可作用于next()函数的对象本身itertor(迭代器)类型,或者obj.next也是iterator ,迭代器是一个惰性序列,因为需要调用next,才会获得元素,迭代完,就不能再次迭代。
c.list、dict、str等是iterable,但不是iterator不过可以通过iter()函数获得一个迭代器对象。

2.生成器:在python中,一边循环,一边计算的机制,称为生成器(generator)。可以理解为一种数据类型,这种数据类型自动实现了迭代器协议。(其他的数据类型需要调用自已的内置iter方法或则iter()的内置函数),所以生成器就是一个可迭代对象。

3.三元运算或三元表达式:

#三元表达式res = 值1 if 条件 else2

这里写图片描述

4.列表生成式:

#生成一个列表L1 = [i for i in range(1,10)]print(L)1#生成一个偶数的列表L2 = [i for i in range(1,10) if i%2 == 0]print(L2)#生成一个奇数的平方的数L3 = [i * i for i in range(1,10) if i%2 == 1]print(L3)

5.生成器表达式:

#生成器表达式G = (i for i in range(1,10))print(G)#generator#取出生成器表达式的值,for循环for i in G:    print(i)#取出生成器表达式的值,next()print(G.__next__())...
#生成器表达式G = (i for i in range(10**100))#列表生成式L = [i for i in range(10**100)#生成器更加省内存,需要一个取一个print(G.__next__())#需要在内存空间创建1-10**100序列print(L)

总结:

a. 把列表解析的[]换成()得到就是生成器表达式。
b. 列表生成式式一个构建一个结果列表,生成器表达式:是返回按需产生结果的一个对象。
c. 列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存。
d. python不但使用迭代器协议让for循环更加通用,大部分内置函数,也是使用迭代器协议访问对象的。如,sum函数是python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议。

5.生成器函数:在python中,使用了yield的函数就称为生成器(generator)。
a.跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,可以理解为:生成器就是一个迭代器

b.在调用生成器运行过程中,每次遇到yield是函数会暂停并保存当前所有的运行信息,返回yield值。并在下一次执行next方法时,从当前位置继续运行。
普通生成器:
这里写图片描述

注:generator保存的是算法,每次调用next方法,就计算出G的下一个元素的值,直到计算到最后一个元素,没有更多元素时,就StopIteration的错误。

当然,上面这种不断调用next(G),用着有点坑,正确的方法是使用for循环,而且不用去担心StopIteration的错误。因为generator也是iterator;

这里写图片描述

generator非常强大,如果计算的算法比较复杂,用for循环无法实现的时候,还可以用函数来实现。

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

这里写图片描述
仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

这里写图片描述
注:如果一个函数定义中包含yield关键字,那么这个函数就不是普通函数,而是一个generator

注:generator和函数执行的流程不一样:

函数是顺序执行,遇到return语句或则最后一行函数函数语句就返回。

而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行从上次返回的yield语句处继续执行

总结:
1.生成器函数语法上和普通函数类似:生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值

2.生成器自动实现迭代器协议,迭代完,就不能再次迭代。

3.状态挂起:生成器使用yield语句返回一个值。挂起该生成器函数的状态。

原创粉丝点击