迭代器

什么是迭代器

迭代器(iterator)是一种用于循环遍历集合对象(如 列表、字典和字符串等)的接口规范,它提供了一种统一的方式来访问集合中的元素。

是一种软件设计模式(中文又称光标 cursor 模式),该模式在不同编程语言中(如Java、C#、Ruby、Python等)均有实现,仅语法略有差异 !

迭代器 (Iterator):这是一个名词,本质指的是那个能够执行迭代任务的对象

在 Python 的定义中,一个对象要成为真正的迭代器(Iterator),必须同时满足两个条件,也就是实现“迭代器协议”

  1. 必须有 __next__方法:用于返回下一个元素。
  2. 必须有 __iter__ 方法:且这个方法必须 返回对象自己(return self)。
class MyIterator:
    def __init__(self, some_str):
        self.some_str_list = some_str.split(',')
        self.index = 0

    def __iter__(self):
        return self  # 关键点:迭代器必须能“返回自己”

    def __next__(self):
        if self.index < len(self.some_str_list):
            result = self.some_str_list[self.index]
            self.index += 1
            return result
        else:
            # 这里的 raise 就是“刹车”,告诉 for 循环:货卖完了,别再点 next 了!
            raise StopIteration

迭代器可以两种方式(迭代)取值

# for循环 迭代
for i in obj:
    print(i)

# __next__迭代
print(obj.__next__())

# 注意:两者不可同时运行,
# 迭代器是一个“单程票”,一旦光标(指针)走到了终点,它就永远留在那里了,
# 如果你想再次遍历,这个旧的迭代器对象已经“废”了,你必须重新创建一个新的迭代器对象

所以,我们可以这么理解这些概念:只要实现了迭代器协议(Iterator Protocol)的类,就是迭代器类,其实例则为迭代器对象! 迭代器对象可以(通过__next__())被迭代 (Iteration)

生么是生成器

自定义迭代器很麻烦啊,有简化方式吗?生成器就是干这个的!生成器(Generator)就是为了让你不再痛苦地去写自定义迭代器类而发明的。写一个自定义迭代器类确实很烦:你要定义类、初始化变量、维护指针状态、写 iter、还要手动 raise StopIteration。而生成器把这些琐事全部自动化了。

def my_generator(some_str):
    # 1. 还是先拆分字符串
    some_str_list = some_str.split(',')
    # 2. 直接遍历,用 yield 吐出结果
    for item in some_str_list:
        yield item  # 自动暂停、自动记录位置、自动在结束时刹车
  • 省掉了 init:你不需要手动初始化 self.index = 0。
  • 省掉了指针维护:在 for item in some_str_list 里,Python 已经帮你处理好了“下一个是谁”的问题。
  • 省掉了 StopIteration:当 for 循环结束,函数运行完毕,生成器会自动抛出刹车信号。
  • 状态保护:每次 yield 之后,函数的所有局部变量都会被“封印”,下次 next() 时自动“解封”继续走。

在普通函数中,return 是“终点”,一旦执行,函数就地解散,局部变量全部销毁。 而在生成器中,yield 是“暂停键”。yield 是为生成器提供的一个强大的功能!

本质:生成器为啥叫生成器?因为它是 迭代器的生成器,为了生成迭代器而存在的,简化了迭代器的创建。这就是它的功能和使命!

转换普通对象为迭代器对象

凡事实现了 __iter__ 方法类型的数据,都可以通过 Python内置的方法 iter 转换为 迭代器(对象),比如 list (列表), str (字符串), tuple (元组), dict (字典), set (集合)等等:

love=['apple','orange','banana']
one=iter(love) # 这就是一个迭代器(对象)

这些数据类型的对象 会被称为 可迭代(Iterable)对象.

迭代器的Next方法

obj.next

迭代器对象有个__next__ 方法,当你触动这个方法时,它内部会发生三件事:

  1. 计算/移动:根据当前指针位置,找到下一个该给你的元素。
  2. 更新状态:把指针往后挪一位,为下一次调用做好准备。
  3. 返回或报错
    • 如果有值,就把值丢出来(return)。
    • 如果后面没东西了,它就抛出异常错误 raise StopIteration
love=['apple','orange','banana']
one=iter(love)

print(one.__next__()) # 输出 apple
print(one.__next__()) # 输出 orange

全局Next函数

python全局函数 next(<font style="color:rgb(35, 41, 48);">one</font>) 函数与 one.__next__() 方法的关系:当你调用全局函数 next(obj) 时,Python 解释器在后台实际上是去调用了该对象的 obj.next() 方法。让你用起来更方便,仅此而已!

什么是迭代

只有迭代器对象(Iterator)才能被执行“迭代”这个动作。

迭代对象.__next__()

迭代 就是“按序逐个访问数据”的动作,其核心方式是利用迭代器协议(__**next__**)实现指针步进,并通过 for 循环(自动)、next()(手动)或 while(条件控制)来触发。

不过 for...in 能够通过自动转换,让“可迭代对象”(Iterable)如字典、列表等不是迭代器的数据结构也跑起来。但本质上也是迭代器在被循环而已!

迭代器核心目标

迭代器模式的核心目标:解耦(让遍历逻辑与数据结构分离)。用户不关心你是什么数据结构(无论是list也好、map也罢),都能提供一个统一的获取内部元素的办法。

否则就要 每一种不同数据结构都有不同的方式去获取内容了

list[index]
dict.get('key')
obj.attr