(期末卷一卷)python迭代对象,迭代器,生成器,超级详解

(期末卷一卷)python迭代对象,迭代器,生成器,超级详解

一 、定义详解

可迭代对象iterable

可迭代的对象的意思是就是说这个实体是可迭代的,例如字符、列表、元组、字典、迭代器等等,可以用for … in进行循环。

而可以使用for循环迭代的标志是内部实现了__iter__方法。

可迭代对象仅含有__iter__的内部方法,你可以通过封装next()方法(python3中为__next__())来将其做成一个迭代器,以生成器(generator,特殊的函数类型的迭代器)为例,你可以通过yield关键字来做一个迭代器,只不过名字被叫做generator,yield可以看做就是为对象添加了__iter__方法和指示下一次迭代的next()/next()方法。

使用isinstance(实体名,Iterable)可判断是否为可迭代对象

迭代器iterator

迭代器就是实现了迭代方式的容器,iterable对象一般只能按默认的正序方式进行迭代,你可以通过为其添加__next__()/next()方法来定制不同的迭代方式,这样通过next方法封装起来的迭代对象生成器就被称作迭代器。

与iterable相比iterator多了一个next()方法,next()方法用于定制for循环时具体的返回值及返回顺序以及处理StopIteration异常等。

iterator必定是iterable的,因此其必然含有__iter__方法,此方法保证了iterator是可以迭代的,个人认为可以将__iter__()方法看做迭代器的入口,此入口告诉python对象是可for循环的,当你还为class定义了__next__方法时python的for循环会直接调用__next__()方法进行迭代。

因此对于实现了__next__方法的迭代器来讲__iter__方法是一个不可或缺的鸡肋方法,不可或缺是因为他是可迭代的标识,鸡肋是因为他不会实质性的起作用,虽然他是迭代器的入口但却不是迭代的起始点,也因此iterator的__iter__方法可以随意返回self或者self.属性或者None。

使用isinstance(实体名,Iterator)可判断是否为迭代器

生成器generator

generator对象是一种特殊的iterator函数,它会在执行过程中保存执行的上下文环境,并在下次循环中从yield语句后继续执行,生成器的标志就是yield关键字。

generator不需要抛出StopIteration异常(你可以看做yield已经在内部实现了StopIteration跳出循环),函数并没有将序列项一次生成,所以generator在实现上可以有无穷个元素,而不需要无穷的存储空间,这在内存优化方面很有用处。

使用isinstance(实体名,Generator)可判断是否为生成器

二 、生成器是特殊的迭代器,但迭代器不一定是生成器

生成器的创建办法有两种:

(1)通过函数创建,称作generator function
(2)通过推导式创建,例如g=(x*2 for x inrange(10)),称作generator expression

isinstance()
该方法用于判断对象是否为Iterator, Iterable, Generator类型,返回 True/False

from collections import Iterator, Iterable, Generator
a=['ShanXi','HuNan','HuBei','XinJiang','JiangSu','XiZang','HeNan','HeBei']
print(isinstance(a,Iterator))  # 检查a 是否是迭代器
print(isinstance(a,Iterable))  # 检查a 是否是迭代对象
print(isinstance(a,Generator)) # 检查a 是否是生成器

方法1:
对列表a的遍历方法有三种:
(1)、普通遍历 for循环
for province in a:print(province)
(2)、函数生成器遍历
for province in generator_list(a):print(province)
(3)、创建生成器后,利用内置函数next()逐个输出进行遍历
print(next(iter))
print(next(iter))
print(next(iter))

def generator_list(a):
    for e in a:
        yield 'Province:\t' + e # 注意yield为生成器标志

# for province in generator_list(a):
#     print(province)

# for province in a:
#     print(province)

iter=generator_list(a)
print(next(iter))
print(next(iter))
print(next(iter))

print(isinstance(iter,Iterator))  # 检查a 是否是迭代器
print(isinstance(iter,Iterable))  # 检查a 是否是迭代对象
print(isinstance(iter,Generator)) # 检查a 是否是生成器

(----再次提醒----)生成器一定是迭代器,但迭代器不一定是生成器

方法2:直接创建迭代器类 :内含两种标志方法 iter(self) next(self)

class iterator_list(object):
    def __init__(self,a):
        self.a=a
        self.len=len(self.a)
        self.cur_pos=-1
    def __iter__(self): # (象征性入口)
        return self
    def __next__(self): # Python3中只能使用__next__()而Python2中只能命名为next()
        self.cur_pos +=1
        if self.cur_pos<self.len:
            return self.a[self.cur_pos]
        else:
            raise StopIteration() # 表示至此停止迭代

iter=iterator_list(a)
print(isinstance(iter,Iterator))  # 检查a 是否是迭代器
print(isinstance(iter,Iterable))  # 检查a 是否是迭代对象
print(isinstance(iter,Generator)) # 检查a 是否是生成器

print(next(iter))
print(next(iter))
print(next(iter))

三、为什么列表本身就可以for循环遍历,还要创建迭代器呢?

你可以理解为,一个程序中创建了不同功能的迭代器类,随时可以调用,代码利用效率高,使用方便。
下面是个实例,加强理解。

list=['a','b','c','d','e','f','g','h','i','j']
# 创建两个迭代器: 一个正序,一个反序,只需要通过两个类就可以方便地创建迭代器对象,不需要频繁地通过for循环遍历序列
class iter_standard(object):
    def __init__(self,list):
        self.list=list
        self.len = len(self.list)
        self.cur_pos = -1
    def __iter__(self):
        return self
    def __next__(self):
        self.cur_pos += 1
        if self.cur_pos<self.len:
            return self.list[self.cur_pos]
        else:
            raise StopIteration()

class iter_reverse(object):
    def __init__(self,list):
        self.list=list
        self.len = len(self.list)
        self.cur_pos = self.len
    def __iter__(self):
        return self
    def __next__(self):
        self.cur_pos -= 1
        if self.cur_pos>=0:
            return self.list[self.cur_pos]
        else:
            raise StopIteration()

for e in iter_standard(list):
    print (e)
print("*"*20)
for e in iter_reverse(list):
    print (e)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白夜的月亮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值