Python中的迭代器和生成器介绍 正确的使用迭代器和生成器

鳄鱼君

发表文章数:642

Vieu四代商业主题

高扩展、安全、稳定、响应式布局多功能模板。

¥69 现在购买
首页 » Python » Python中的迭代器和生成器介绍 正确的使用迭代器和生成器

Python中的生成器

通过列表生成式,我们可以直接创建一个列表。但是受内存限制,列表容量肯定是有限的。如果创建一个包含1000万个元素的列表,不仅会占用很大的储存空间,我们仅仅只需要访问前面的几个元素,那后面的大多数元素占用的空间都白白浪费了。

在Python中一边循环一边计算的机制,称为生成器:generator,它具有一下特点:

  • 1.只有在当前调用时才会生成相应的数据
  • 2.只记录当前位置
  • 3.只有一个.__next()__方法

实例引入

#列表生成式
def fun(i):
    return i*i
l=[i for i in range(10)] #列表生成式
list=[fun(i) for i in range(10)]  #可以是函数,实现更多的功能
l[1] #列表生成式,我们可以采用切片来取后面的值,但是生成器就不行了

#生成器
g=(i for i in range(10))  #返回的是一个地址,数据还不存在generator object
for k in g:
     print(k)
# print(g.__next__()) 你可以使用.__next()__方法一个一个的调用生成器
# print(g.__next__())
#跟列表生成式的区别就是你不调用,它根本就没有

斐波那契数列

著名的斐波那契数列,除第一个元素和第二个元素外,任意一个数都可以由前两个数相加得到:1,1,2,3,5,8,13,21,34……,我们可以采用函数把它打印出来

def fun(max):
    n, a, b = 0, 0, 1
    while n<max:
        print(b,end=' ')
        a,b = b,a+b
        n+=1
fun(10)

注意

a=0
b=1

# a = b
# b = a + b
# print(a,b) 结果(1,2)
a,b=b,a+b
print(a,b) #结果(1,1)
#两者不可以混迹,你也可以单独分开采用断点尝试一下

上面我们只是用函数,把斐波那契数列打印出来了,它离生成器只有一步之遥,要把fun函数变成generator,只需要把print(b )修改为yield b即可。

def fun(max):
    n, a, b = 0, 0, 1
    while n<max:
        yield b
        a,b = b,a+b
        n+=1
print(fun(10))  #这样就变成了生成器,你可以采用.__next()__方法来获取一个值试试
f=fun(10)
print(f.__next__())
print(f.__next__())
print("我可以随时插进去")
print(f.__next__())
print(f.__next__())
print("我还可以随时出来")
print(f.__next__())

我们可以发现,在使用函数打印斐波那契数列时,是一下子全部打印完的,我们不能在中途做任何事情,而生成器则不同了,我们可以在取值时,做一些事情。一个函数中存在yield,它就不在时函数了,是一个生成器。我们采用.__next()__方法一个一个的调用生成器,很好,fun(10)有10次,我们调用100次呢,会发生什么,会出现StopIteration异常报错

def fun(max):
    n, a, b = 0, 0, 1
    while n<max:
        yield b
        a,b = b,a+b
        n+=1
    return '我是一个小草'
f=fun(6)
while True:
    try:
        g=next(f) #内置方法等同于.__next()__
        print('g:',g)
    except StopIteration as e:
        print('出错了...',e)
        break

我们添加了一个return返回值,然后还抓取了StopIteration报错信息,出错就会显示return的返回值

Python中的迭代器

我们首先要知道,可以用for循环的数据类型有:List列表、Tuple元组、Dict字典、Set集合、Str字符串、Bytes字节、生成器generator、带yield的generator函数。这些可以直接作用于for循环的对象称之为可迭代对象(Iterable).你可以使用isinstance()函数来判断是否是Iterable对象

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

可迭代对象和迭代器不是一回事,同样我们也可以使用isinstance()来判断一个对象是否是Iterator对象,注意两者不可混记!

#由于我是用的是3.7版本的,所以需要从collections.abc中导入
#如果你从collections导入会报错,但是不碍事,在3.8就会废除collectons.abc
from collections.abc import Iterable   #Iterable可迭代对象
from collections.abc import Iterator   #Iterator迭代器

#判断是否为可迭代对象,返回结果都是可迭代对象
print(isinstance([1,23,445,5],Iterable))
print(isinstance((12,32,14,21,31),Iterable))
print(isinstance('我是一个字符串',Iterable))
print(isinstance({'name':'zjj','love':'wff'},Iterable))
print(isinstance({'zjj','wff','xxk','zgp'},Iterable))
#判断是否为迭代器
print(isinstance( (i for i in range(10)),Iterator)) #迭代器
print(isinstance(  [1,23,3,4],Iterator))
print(isinstance(  {'zsda',1232,'zjj'},Iterator))
print(isinstance( ('ZJJ','awdadw') ,Iterator))
print(isinstance( 'ZJJ' ,Iterator))
#你也可以使用dir()方法来查看该对象所有的方法,只要含有__next__,就是迭代器
f=(i for i in range(10))
print(dir(f))

以上代码可以发现,生成器都是迭代器(Iterator),但是可迭代对象不是迭代器,因为它们不符合迭代器的定义,但你可以使用iter()函数,把可迭代对象变成迭代器.

iter( )

iter( )函数可以把可迭代对象转换为迭代器,那么同样就可以使用.__next()__方法来取值

from collections.abc import Iterator   #Iterator迭代器


#判断是否为迭代器
print(isinstance( (i for i in range(10)),Iterator)) #迭代器
print(isinstance(  iter([1,23,3,4]),Iterator))
print(isinstance(  iter({'zsda',1232,'zjj'}),Iterator))
print(isinstance( iter(('ZJJ','awdadw')) ,Iterator))
print(isinstance( iter('ZJJ') ,Iterator))

迭代器(Iterator)可以表示一个无限大的数据流,而使用List列表是永远不可能存储全体自然数的。

未经允许不得转载:作者:鳄鱼君, 转载或复制请以 超链接形式 并注明出处 鳄鱼君
原文地址:《Python中的迭代器和生成器介绍 正确的使用迭代器和生成器》 发布于2019-12-08

分享到:
赞(0) 赏杯咖啡

评论 抢沙发

9 + 7 =


文章对你有帮助可赏作者一杯咖啡

支付宝扫一扫打赏

微信扫一扫打赏

Vieu4.6主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。
切换注册

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录
切换登录

注册