python 迭代对象、迭代器大解析

迭代对象

结论:

  • 1、 拥有__iter___() 方法
items_lis = [1,2,3]
items_str = 'hello world'
from collections.abc import Iterator
from collections.abc import Iterable

print(isinstance(items_lis, Iterable))	# True		迭代对象
print(isinstance(items_lis, Iterator))	# False		迭代器

print(isinstance(items_str, Iterable))	# True		迭代对象
print(isinstance(items_str, Iterator))	# False		迭代器
  • 可迭代对象之所以可以使用for循环,是因为在运行时,for循环会自动调用iter()方法,变为迭代器
  • 比如我想获取列表中的值,但是不用for循环,怎么办,只能用while方法
  • 之所以能用while,通过索引的方式输出,是因为列表(list)实现了__getitem__() 方法

列表同时有__item__() 和__getitem__() 会优先使用__item__()

当只有__getitem__(),使用for循环时,python解释器会自动生成默认的迭代器,然后这个迭代器会利用__getitem__来进行遍历

当只有__item__() 的时候,构建迭代器来输出,使用iter(),或者使用__next__()构建迭代器

# 不使用for循环,打印列表,是因为列表有 __getitem__() 方法
def iterator(item):
    index = 0
    try:
        while True:
            print(item[index])
            index += 1
    except:
        print('数据已全部输出')

iterator(items_lis)

# 1
# 2
# 3
# 数据已全部输出
  • 使用 iter() 方法构建迭代器,构建迭代器的时候,你得是可迭代对象,因为要遵守迭代器协议
  • 下面可以使用next(),那是因为我是一个迭代器,迭代器有__next__() 方法
  • 注释的print,两种,哪种都行
# 我照样不适用for循环,因为你只要是一个可迭代对象,for就给你后台自己创个迭代器出来

items_lis = [1,2,3]
items_lis_iter = iter(items_lis)

def iterator(item):
    try:
        while True:
            print(next(item))
            # print(items_lis_iter.__next__())
    except:
        print('数据都输出完了')

iterator(items_lis_iter)
# 1
# 2
# 3
# 数据都输出完了
  • 当你是一个迭代对象,你用next(),或者__next__(),那指定报错
  • 说我不是一个迭代器,哈哈哈哈,所以可迭代对象,那就是一个对象,要输出,还得靠迭代器
items_lis = [1,2,3]
print(next(items_lis))

Traceback (most recent call last):
  File "F:/Py_Project/tools/3.py", line 14, in <module>
    print(next(items_lis))
TypeError: 'list' object is not an iterator

迭代器

结论:

  • 1、拥有__iter__() 方法
  • 2、拥有__next__()方法
  • 看上面对比说的,应该能懂一点吧
  • 我直接构建一个迭代器吧,然后我在迭代器类里面没有写__iter__()方法,也可以运行,是因为迭代器有__iter__(),两个组合在一起了

class MyName:							# 类 MyName 就是迭代对象
    def __init__(self, name):
        self.name = name
        self.index = 0

    def __iter__(self):					# 迭代对象
        return MyIterator(self.name)	# 返回迭代器

class MyIterator:						# 类 MyIterator 迭代器
    def __init__(self, data):
        self.iter_list = data
        self.index = 0

    def __next__(self):					# 迭代器关键,这里写不写__iter__(),无所谓,因为迭代器有了
        try:
            iter_tar = self.iter_list[self.index]
        except IndexError:
            raise StopIteration
        self.index += 1
        return iter_tar

if __name__ == '__main__':
    a = MyName(['a', 'b', 'c'])
    # a = MyIterator(['a', 'b', 'c'])
    for i in a:
        print(i)
  • 同样,我直接在一个类里面写了__iter__()和__next__(),我是可迭代对象,同时也是迭代器,
  • 我直接在__iter__()里面return self,给自己return了,是因为我要自己当可迭代对象,return出去
  • 搭配__next__()完成迭代器
class MyIterator:
    def __init__(self, data):
        self.iter_list = data
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        try:
            iter_tar = self.iter_list[self.index]
        except IndexError:
            raise StopIteration
        self.index += 1
        return iter_tar

if __name__ == '__main__':
    a = MyIterator(['a', 'b', 'c'])
    for i in a:
        print(i)

题外话:

因为在python的所有迭代场景中所作用的对象必须是可迭代对象(Iterable),因此迭代器(Iterator)要想在迭代场景中使用,就必须是Iterable对象;要成为Iterable对象就必须遵守Iterable协议,通过实现__iter__函数来满足Iterable协议,从而成为Iterable对象。个人认为,迭代器实现__iter_函数的目的是为了兼容python已有的迭代场景和工具,例如:for循环、列表解析、map、sum、zip等等。

如果迭代器不实现__iter_方法的话,上述函数和工具都无法用来对该迭代器进行迭代,只能通过人工调用next()方法来进行迭代,这与python “简洁统一” 的设计原则是相违背的,所以迭代器要实现__iter__方法。

直接看源码,就懂了
from collections.abc import Iterator
from collections.abc import Iterable

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值