Python可迭代对象与迭代器详解
首先先来了解几个概念
可迭代对象 (Iterable) : 实现了 __iter__ 方法的对象就是可迭代对象 (生成迭代器的对象)
迭代器 (iterator) : __iter__ 方法返回的, 同时实现了 __iter__ 方法与 __next__ 方法的对象就是迭代器 (真正执行迭代的对象)
迭代: 调用迭代器的 __next__ 方法使之返回一个元素
迭代器耗尽: 迭代器主动抛出了StopIteration异常, 就表示迭代器耗尽, Python会自动处理这个异常
(迭代器同时也是可迭代对象, 可迭代对象不一定是迭代器)
(可迭代对象是用来创建迭代器的, 迭代器是通过可迭代对象创建的, 真正执行迭代的是迭代器)
通过 iter(Iterable) 内置函数 创建迭代器
通过 next(iterator) 内置函数或者 iterator.send(object) 方法创建迭代器进行 迭代
实现迭代器
请仔细反复阅读以下代码, 可以复制到代码编辑器运行查看
# 可迭代对象
class MyIterable(object):
def __init__(self, items):
self.items = items
def __iter__(self):
print('MyIterable.__iter__')
# 创建一个迭代器
return MyIterator(self.items)
# 迭代器
class MyIterator(object):
def __init__(self, items):
self.items = items
self.len = len(items)
self.index = 0
def __iter__(self):
print('MyIterator.__iter__')
# 因为自身实现了__iter__方法, 所以自身就是一个可迭代对象
# 因为自身同时实现了__iter__与__next__方法, 所有自身就是一个迭代器
return self
def __next__(self):
print('MyIterator.__next__')
if self.index < self.len:
res = self.items[self.index]
self.index += 1
return res
# 通知迭代器耗尽
raise StopIteration
# 创建一个可迭代对象
my_iterable = MyIterable(list('ABCDEF'))
# 通过iter内置函数创建一个迭代器
my_iterator = iter(my_iterable)
# 执行迭代
print(next(my_iterator))
""" 执行结果
MyIterable.__iter__
MyIterator.__next__
A
对照代码与执行结果再来读一遍下面这句话
(可迭代对象是用来创建迭代器的, 迭代器是通过可迭代对象创建的, 真正执行迭代的是迭代器)
有没有了解? 没有了解请再读一遍, 然后看下面的代码
"""
# 因为MyIterator类同时实现了__iter__与__next__方法所以它本身就是一个迭代器与可迭代对象
# 先把它当可迭代对象
my_iterable = MyIterator(list('ABCDEF'))
# 然后创建迭代器
my_iterator = iter(my_iterable)
# 执行迭代
print(next(my_iterator))
""" 执行结果
MyIterator.__iter__
MyIterator.__next__
A
对照代码与执行结果再来读一遍下面这句话
(可迭代对象是用来创建迭代器的, 迭代器是通过可迭代对象创建的, 真正执行迭代的是迭代器)
有没有了解? 了解了再看下面的代码
"""
# 直接创建一个迭代器
my_iterator = MyIterator(list('ABCDEF'))
# 执行迭代
print(next(my_iterator)
""" 执行结果
MyIterator.__next__
A
懵逼不?
很简单, 因为MyIterator类同时实现了__iter__与__next__方法所以它本身就是一个迭代器与可迭代对象
"""
现在来思考几个问题
- 可迭代对象为什么可以迭代?
- 可迭代对象一定可以迭代吗?
- 迭代器一定可以迭代吗?
- 迭代器是可迭代对象吗?
- for循环为什么可以迭代?
如果您已经有了明确答案, 说明我的努力没有白费, 您已经掌握了可迭代对象与迭代器的精髓, 请帮我点赞哦
来源:CSDN
作者:序日新说
链接:https://blog.csdn.net/weixin_44221705/article/details/103602405