迭代器与生成器

迭代器

迭代是什么

我们知道可以对list,tuple,dict,str等数据类型使用for...in...的循环语法,从中依次取出数据,这个过程叫做遍历,也称迭代(迭代是访问集合元素的一种常用方式)

可迭代对象是什么

可以用for...in...循环语句从中取出数据的对象,就是可迭代对象,例如:列表、元组、字典、字符串都是可迭代对象;而整数、浮点数、布尔值均是不可迭代对象

迭代器是什么

每迭代一次即在for...in...中每循环一次,都会返回对象中的下一条数据,一直向后读取数据直到迭代了所有数据之后结束,而在这个过程中应该有一个“人”去记录每次访问到了第几条数据,以便每次迭代都可以返回下一条数据,外面把这个每次能帮我们进行数据迭代的“人”,称之为迭代器(Iterator)

例如:老师安排学生每节课上课前进行演讲,按照学号顺序进行,A同学这节课演讲,老师会记住A同学演讲过了,那么下节课就是B同学进行演讲了....以此类推,在这里,老师就充当了“迭代器”的角色了。

如何获取可迭代对象的迭代器

我们可以通过iter()内置函数取得可迭代对象的迭代器

list=[1,2,3,4] #list是可迭代对象
it=iter(list) #创建迭代器对象:通过lter()方法取得list的迭代器
print(it)

结果:
<list_iterator object at 0x000002235A16A460>

利用next()函数通过迭代器获取下一个位置的值

注意:当我们迭代完最后一个数据之后,再次调用next()函数时会抛出StopIteration的异常,来告诉我们所有数据都已迭代完成,不用再执行next()函数了

list=[1,2,3,4] #list是可迭代对象
it=iter(list) #创建迭代器对象:通过lter()方法取得list的迭代器
print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))

结果:
1
2
3
4
Traceback (most recent call last):
  File "D:\Python_test\day1\xx.py", line 7, in <module>
    print(next(it))
StopIteration

判断一个对象是否可迭代

isinstance(object,classinfo)内置函数可以判断一个对象是否是一个已知的类型,类似 type()。

  • object -- 实例对象。
  • classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组。

collections模块里的Iterable,凡是可迭代对象都是这个类的实例对象。

import collections

print(isinstance([1,2,3],collections.Iterable))
print(isinstance((1,2,3),collections.Iterable))
print(isinstance({"name":"chichung","age":23},collections.Iterable))
print(isinstance("sex",collections.Iterable))
print(isinstance(123,collections.Iterable))
print(isinstance(True,collections.Iterable))
print(isinstance(1.23,collections.Iterable))

结果:
True
True
True
True
False
False
False

可迭代对象如何获取迭代器

迭代对象是由collections模块里的Iterable类创建出来的实例的,你写一个列表,它是Iterable类创建的实例对象

class Iterable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __iter__(self):  # 注意__iter__(self)方法
        while False:
            yield None

由Iterable创建的对象,是有一个方法_iter_(self)的,此方法返回一个迭代器,所以,由Iterable类创建的实例对象,是可以拿出一个迭代器的。

之所以Iterable类创建的对象是可迭代对象,是因为Iterable类有这个方法(_iter_(self))!

import collections

class BecomeIterable:
    def __iter__(self):
        """返回一个空的迭代器"""
        return None
people = BecomeIterable()
print(isinstance(people, collections.Iterable))

结果:
True

迭代器为何能用next()函数进行迭代呢

我们知道使用iter()函数,在可迭代对象中获取迭代器,Iterator=iter([1,2,3,4]),使用next(),是因为iter()函数能调用可迭代对象的方法__iter__(),从而返回一个迭代器。如何返回?__iter__()方法是使用collections模块里的Iterator类来创建一个迭代器对象。

class Iterator(Iterable):

    __slots__ = ()

    @abstractmethod
    def __next__(self):
        'Return the next item from the iterator. When exhausted, raise StopIteration'
        raise StopIteration

    def __iter__(self):
        return self

如果超出迭代方位就抛出StopIteration异常

创建一个迭代器类

class MyIterator():
    def __init__(self):
        self.list = []
        self.position = 0

    def add_name(self,name):
        self.list.append(name)

    def __iter__(self):
        return self  # 返回一个迭代器

    def __next__(self):
        if self.position < len(self.list):
            item = self.list[self.position]
            self.position += 1
            return item
        else:
            raise StopIteration


people = MyIterator()  # people对象既是一个迭代器,也是一个可迭代对象
people.add_name("张三")
people.add_name("李四")
people.add_name("王五")

# 把people当做一个迭代器来看时
print(next(people))
print(next(people))
print(next(people))

# 把humen当做一个可迭代对象来看时
humen = MyIterator()  # 因为迭代器只能用一次,再用会抛出错误,所以需要再创建
humen.add_name("张三")
humen.add_name("李四")
humen.add_name("王五")
iterator = iter(humen)  # iter()方法获取可迭代对象的迭代器
print(next(iterator))
print(next(iterator))
print(next(iterator))

结果:
张三
李四
王五
张三
李四
王五

生成器

yieId的函数被称为生成器(generator)

与普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作(生成器就是迭代器)

在调用生成器运行的过程中,每次遇到yieId时函数会暂停并保存当前所有的运行信息,返回yieId的值,并在下一次执行next()方法时,从当前位置继续运行(调用一个生成器函数,返回一个迭代器对象)

使用斐波那契数列写一个实例

import sys
def fibonacci(n): #生成器函数-斐波那契
    a,b,counter =0,1,0
    while True:
        if (counter > n):
            return
        yield a
        a,b,=b,a+b
        counter += 1
f=fibonacci(10) #f是一个迭代器,由生成器返回生成

while True:
    try:
        print(next(f),end=" ")
    except StopIteration:
        sys.exit()

结果:
0 1 1 2 3 5 8 13 21 34 55 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值