当前位置:首页>python>Python学习--迭代器详解

Python学习--迭代器详解

  • 2026-09-02 19:33:41
Python学习--迭代器详解

一、什么是迭代器?

1. 迭代器的定义

迭代器是一个可以记住遍历位置的对象。它实现了迭代器协议,即包含 __iter__() 和 __next__() 方法。

2. 迭代器协议

# 迭代器必须实现的两个方法:- __iter__(): 返回迭代器对象本身- __next__(): 返回下一个元素,没有元素时抛出 StopIteration

3. 可迭代对象 vs 迭代器

# 可迭代对象 (Iterable): 可以返回迭代器的对象(实现了 __iter__)# 迭代器 (Iterator): 可以逐个返回元素的对象(实现了 __iter__ 和 __next__)# 关系图:# 可迭代对象 ──(iter())──> 迭代器 ──(next())──> 元素

二、基础概念

1. 最简单的例子

# 列表是可迭代对象,但不是迭代器my_list = [1, 2, 3]print(f"列表是可迭代对象: {hasattr(my_list, '__iter__')}")print(f"列表是迭代器: {hasattr(my_list, '__next__')}")# 获取迭代器iterator = iter(my_list)print(f"迭代器是可迭代对象: {hasattr(iterator, '__iter__')}")print(f"迭代器是迭代器: {hasattr(iterator, '__next__')}")# 使用迭代器print(next(iterator))  # 1print(next(iterator))  # 2print(next(iterator))  # 3# print(next(iterator))  # StopIteration

2. 迭代器的工作原理

# for 循环的工作原理my_list = [1, 2, 3]# Python 内部是这样做的:iterator = iter(my_list)  # 1. 获取迭代器while True:    try:        item = next(iterator)  # 2. 获取下一个元素        print(item)             # 3. 处理元素    except StopIteration:       # 4. 捕获结束信号        break                    # 5. 退出循环# 等价于:for item in my_list:    print(item)

三、自定义迭代器

1. 最简单的迭代器

class Counter:    """计数器迭代器"""    def __init__(self, start, end):        self.current = start        self.end = end    def __iter__(self):        """返回迭代器本身"""        return self    def __next__(self):        """返回下一个元素"""        if self.current >= self.end:            raise StopIteration        value = self.current        self.current += 1        return value# 使用counter = Counter(1, 5)for num in counter:    print(num, end=' ')  # 1 2 3 4print()# 注意:迭代器只能使用一次print(list(counter))  # [] 已经用完了

2. 无限迭代器

class FibonacciIterator:    """斐波那契数列迭代器(无限)"""    def __init__(self):        self.a = 0        self.b = 1    def __iter__(self):        return self    def __next__(self):        value = self.a        self.a, self.b = self.b, self.a + self.b        return value# 使用fib = FibonacciIterator()for i, num in enumerate(fib):    print(num, end=' ')    if i >= 10:  # 取前10个        breakprint()  # 0 1 1 2 3 5 8 13 21 34 55# 注意:无限迭代器需要手动停止

3. 可重置的迭代器

class ResettableIterator:    """可重置的迭代器"""    def __init__(self, data):        self.data = data        self.index = 0    def __iter__(self):        return self    def __next__(self):        if self.index >= len(self.data):            raise StopIteration        value = self.data[self.index]        self.index += 1        return value    def reset(self):        """重置迭代器"""        self.index = 0# 使用it = ResettableIterator([1, 2, 3, 4, 5])print("第一次遍历:")for item in it:    print(item, end=' ')print()print("重置后再次遍历:")it.reset()for item in it:    print(item, end=' ')print()

四、内置迭代器工具

1. iter() 函数

# 从可迭代对象创建迭代器my_list = [1, 2, 3]it = iter(my_list)print(next(it))  # 1# 使用哨兵值创建迭代器import sysdef read_until_q():    """读取输入直到输入 'q'"""    return input("输入 (输入 'q' 退出): ")# 当函数返回 'q' 时停止for line in iter(read_until_q, 'q'):    print(f"你输入了: {line}")

2. next() 函数

it = iter([1, 2, 3])# 基本使用print(next(it))  # 1# 带默认值print(next(it, '没有更多了'))  # 2print(next(it, '没有更多了'))  # 3print(next(it, '没有更多了'))  # '没有更多了'

3. enumerate() - 枚举迭代器

fruits = ['apple', 'banana', 'orange']# 获取索引和值for i, fruit in enumerate(fruits):    print(f"{i}: {fruit}")# 指定起始索引for i, fruit in enumerate(fruits, start=1):    print(f"{i}: {fruit}")

4. zip() - 并行迭代

names = ['Alice', 'Bob', 'Charlie']ages = [25, 30, 35]cities = ['New York', 'London', 'Tokyo']# 并行迭代多个序列for name, age, city in zip(names, ages, cities):    print(f"{name} is {age} years old, lives in {city}")# 处理不等长序列numbers = [1, 2, 3]letters = ['a', 'b']for num, letter in zip(numbers, letters):    print(f"{num}:{letter}")  # 只输出两个,第三个被忽略# 使用 zip_longest 处理不等长from itertools import zip_longestfor num, letter in zip_longest(numbers, letters, fillvalue='?'):    print(f"{num}:{letter}")

五、最佳实践和注意事项

1. 迭代器使用原则

class IteratorBestPractices:    """迭代器最佳实践"""    # 1. 一次性的迭代器    def once_demo(self):        it = iter([1, 2, 3])        print(list(it))  # [1, 2, 3]        print(list(it))  # [] - 已经用完了    # 2. 使用生成器简化    def generator_demo(self):        def countdown(n):            while n > 0:                yield n                n -= 1        # 简单清晰        for x in countdown(5):            print(x)    # 3. 处理大文件    def file_processing_demo(self):        def read_lines(file_path):            with open(file_path) as f:                for line in f:                    yield line.strip()        # 内存友好        for line in read_lines('large_file.txt'):            process(line)    # 4. 提前退出    def early_exit_demo(self):        def find_first(iterable, predicate):            for item in iterable:                if predicate(item):                    return item            return None        # 找到就停止,不继续遍历        result = find_first(range(1000000), lambda x: x > 500000)

2. 常见陷阱

# 陷阱1:多次使用迭代器it = iter([1, 2, 3])print(list(it))  # [1, 2, 3]print(list(it))  # [] - 已经空了# 正确做法:重新创建it = iter([1, 2, 3])print(list(it))it = iter([1, 2, 3])  # 重新创建print(list(it))# 陷阱2:修改可迭代对象data = [1, 2, 3, 4]for item in data:    if item == 2:        data.remove(item)  # 危险!会跳过元素print(data)  # [1, 3, 4] - 3 被跳过了# 正确做法:创建新列表data = [1, 2, 3, 4]data = [x for x in data if x != 2]# 陷阱3:迭代器耗尽def process_items(items):    for item in items:        yield process(item)items = process_items(data)if items:  # 错误:迭代器总是 True    print("有数据")# 正确做法items = list(process_items(data))  # 转换为列表if items:    print("有数据")# 陷阱4:无限迭代器没有停止条件def infinite():    i = 0    while True:        yield i        i += 1gen = infinite()# for x in gen:  # 无限循环!#     print(x)# 正确做法:设置限制for i, x in enumerate(gen):    if i >= 10:        break    print(x)

3. 自定义迭代器模板

class IteratorTemplate:    """迭代器模板"""    def __init__(self, data):        self.data = data        self.index = 0    def __iter__(self):        """返回迭代器本身"""        return self    def __next__(self):        """返回下一个元素"""        if self.index >= len(self.data):            raise StopIteration        value = self._process_item(self.data[self.index])        self.index += 1        return value    def _process_item(self, item):        """处理单个项目(可被子类重写)"""        return item    def reset(self):        """重置迭代器"""        self.index = 0    def __len__(self):        """返回可迭代长度"""        return len(self.data) - self.index    def __repr__(self):        return f"{self.__class__.__name__}(剩余: {len(self)})"# 使用class SquareIterator(IteratorTemplate):    def _process_item(self, item):        return item ** 2it = SquareIterator([1, 2, 3, 4, 5])for value in it:    print(value, end=' ')  # 1 4 9 16 25print()print(it)  # SquareIterator(剩余: 0)

总结

迭代器的优点:

  1. 内存高效:一次只产生一个元素

  2. 惰性计算:需要时才计算

  3. 无限序列:可以表示无限数据流

  4. 统一接口:所有迭代器使用相同的方式操作

何时使用迭代器:

  • 处理大数据集

  • 流式数据处理

  • 需要惰性计算的场景

  • 表示无限序列

  • 需要统一的遍历接口

何时避免使用迭代器:

  • 需要随机访问

  • 需要多次遍历

  • 数据量很小

  • 需要索引操作

请在微信客户端打开

最新文章

随机文章