21 迭代器(Iterator)详解

1、定义:

python Iterator(迭代器)是一个可以记住遍历位置的对象。它从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器有两个基本方法:__iter__()__next__()

  • __iter__() 方法返回迭代器对象本身。这是为了使迭代器对象能够与for循环等使用迭代协议的代码兼容。
  • __next__() 方法返回容器中的下一个值。如果没有更多的元素可供返回,则会触发 StopIteration 异常来通知调用者。

2、迭代器的工作原理

当你使用一个循环如for循环去遍历时,背后实际上是在重复调用迭代器的__next__()方法,并且在捕获到StopIteration异常时自动停止循环。这种机制使得我们可以高效地遍历大型数据集,而不需要一次性将所有数据加载进内存。

3、快速掌握迭代器的要点

1、基本概念:

  • 迭代器是实现了__iter__和__next__方法的对象
  • 迭代器一次只处理一个元素,节省内存
  • 迭代器只能向前移动,不能回退

2、创建方式:

  • 使用iter()函数从可迭代对象获取迭代器
  • 创建自定义类实现迭代器协议
  • 使用生成器函数(带yield)创建迭代器

3、常用工具:

  • itertools模块提供了强大的迭代器工具
  • 无限迭代器:count, cycle, repeat
  • 组合迭代器:chain, zip_longest
  • 过滤和映射:filter, map

4、实际应用:

  • 数据处理管道
  • 大数据集处理
  • 日期范围生成

示例代码:

"""
Python迭代器(Iterator)详解

迭代器是Python中一个重要的概念,它提供了一种访问集合元素的方式,而不需要暴露集合的内部结构。
迭代器对象实现了__iter__()和__next__()两个方法(迭代器协议)。

迭代器的核心优势:
1. 内存效率高 - 一次只在内存中保存一个元素
2. 惰性计算 - 只在需要时才计算下一个值
3. 可以表示无限序列 - 不需要预先计算所有值
4. 组合性强 - 可以构建复杂的数据处理管道

"""

# 第一部分:迭代器基础概念
print("=" * 50)
print("第一部分:迭代器基础概念")
print("=" * 50)

# 1.1 可迭代对象(Iterable)与迭代器(Iterator)的区别
print("\n1.1 可迭代对象与迭代器的区别:")
print("可迭代对象: 实现了__iter__()方法,可以返回迭代器")
print("迭代器: 实现了__iter__()和__next__()方法,可以逐个返回元素")
# 补充说明:for循环可以遍历任何可迭代对象,它会自动调用iter()获取迭代器,然后重复调用next()

# 1.2 内置可迭代对象示例
print("\n1.2 内置可迭代对象示例:")
# 使用dir()函数检查对象是否包含__iter__方法,从而判断是否可迭代
print(f"列表是可迭代的: {'__iter__' in dir([])}")  # 列表是最常见的可迭代对象
print(f"字典是可迭代的: {'__iter__' in dir({})}")  # 字典默认迭代键
print(f"集合是可迭代的: {'__iter__' in dir(set())}")  # 集合中的元素无序且唯一
print(f"元组是可迭代的: {'__iter__' in dir(())}")  # 元组是不可变的序列
print(f"字符串是可迭代的: {'__iter__' in dir('')}")  # 字符串可以按字符迭代

# 1.3 获取迭代器并使用
print("\n1.3 获取迭代器并使用:")
my_list = [1, 2, 3, 4, 5]
# 获取迭代器 - iter()函数是获取迭代器的标准方式
iterator = iter(my_list)  # 等同于 my_list.__iter__()
print(f"迭代器类型: {type(iterator)}")  # 显示迭代器的实际类型

# 使用next()获取下一个元素 - next()是从迭代器获取值的标准方式
print(f"第一个元素: {next(iterator)}")  # 等同于 iterator.__next__()
print(f"第二个元素: {next(iterator)}")  # 每次调用next()都会返回下一个元素
print(f"第三个元素: {next(iterator)}")  # 并且迭代器会记住当前位置

# 迭代器用尽后会抛出StopIteration异常 - 这是Python标准的迭代结束信号
print("\n迭代器耗尽示例:")
try:
    # 继续获取剩余元素
    print(f"第四个元素: {next(iterator)}")  # 正常获取第四个元素
    print(f"第五个元素: {next(iterator)}")  # 正常获取第五个元素
    # 超出范围 - 列表只有5个元素,所以第六次调用next()会抛出异常
    print(next(iterator))
except StopIteration:
    print("迭代器已耗尽,抛出StopIteration异常")  # for循环会自动处理这个异常并停止迭代


# 第二部分:创建自定义迭代器
print("\n" + "=" * 50)
print("第二部分:创建自定义迭代器")
print("=" * 50)
# 自定义迭代器需要实现迭代器协议:__iter__()和__next__()方法

# 2.1 基本迭代器类
print("\n2.1 基本迭代器类:")


class CountDown:
    """一个简单的倒计时迭代器

    这个类演示了如何创建一个基本的迭代器,从指定数字倒数到1
    """

    def __init__(self, start):
        """初始化倒计时的起始值

        参数:
            start: 倒计时的起始数字
        """
        self.start = start  # 保存初始值,这将是我们开始倒数的数字

    def __iter__(self):
        """返回迭代器对象自身

        这个方法使对象可迭代。在迭代器类中,它应该返回self。
        当使用for循环时,Python会自动调用这个方法获取迭代器。
        """
        # 迭代器必须返回自身,这样才能在for循环中使用
        return self

    def __next__(self):
        """返回下一个值或抛出StopIteration异常

        这个方法定义了如何获取序列中的下一个值。
        当没有更多值可返回时,应该抛出StopIteration异常。
        """
        if self.start <= 0:
            # 当没有更多元素时抛出异常,这会通知for循环停止迭代
            raise StopIteration

        # 保存当前值,因为我们要在返回前修改self.start
        current = self.start
        # 更新状态,为下次迭代做准备
        self.start -= 1
        # 返回当前值
        return current


# 使用自定义迭代器
countdown = CountDown(5)  # 创建一个从5倒数的迭代器
print("倒计时:")
for num in countdown:  # for循环会自动调用__iter__()和__next__()
    print(num, end=" ")  # 输出: 5 4 3 2 1
print("\n")

# 2.2 斐波那契数列迭代器
print("2.2 斐波那契数列迭代器:")


class Fibonacci:
    """生成斐波那契数列的迭代器

    斐波那契数列:每个数是前两个数的和,从0和1开始
    例如:0, 1, 1, 2, 3, 5, 8, 13, ...
    """

    def __init__(self, limit):
        """初始化,设置上限

        参数:
            limit: 要生成的斐波那契数的数量
        """
        self.limit = limit  # 限制生成的数量
        self.a, self.b = 0, 1  # 初始化前两个数
        self.count = 0  # 计数器,跟踪已生成的数量

    def __iter__(self):
        """返回迭代器自身"""
        return self  # 同样,迭代器的__iter__方法返回self

    def __next__(self):
        """返回下一个斐波那契数"""
        if self.count >= self.limit:
            # 达到限制数量时停止迭代
            raise StopIteration

        # 保存当前值(a)作为结果
        result = self.a
        # 更新状态:a变为b,b变为a+b(斐波那契数列的核心逻辑)
        self.a, self.b = self.b, self.a + self.b
        self.count += 1  # 增加计数器

        return result  # 返回当前的斐波那契数


# 使用斐波那契迭代器
fib = Fibonacci(10)  # 创建一个生成10个斐波那契数的迭代器
print("斐波那契数列前10项:")
for num in fib:  # 自动迭代
    print(num, end=" ")  # 输出: 0 1 1 2 3 5 8 13 21 34
print("\n")


# 第三部分:迭代器的高级用法
print("=" * 50)
print("第三部分:迭代器的高级用法")
print("=" * 50)
# Python的itertools模块提供了许多强大的迭代器工具

# 3.1 无限迭代器
print("\n3.1 无限迭代器:")
import itertools  # 导入itertools模块,它包含许多有用的迭代器函数

# count: 从n开始无限计数 - 创建一个永不停止的计数器
counter = itertools.count(10, 2)  # 从10开始,步长为2:10, 12, 14, 16, ...
print("itertools.count示例(从10开始,步长为2):")
for i, num in enumerate(counter):  # enumerate返回索引和值的元组
    if i >= 5:  # 只显示前5个,否则会无限循环
        break
    print(num, end=" ")  # 输出: 10 12 14 16 18
print()

# cycle: 无限循环迭代元素 - 循环遍历一个序列,到末尾后重新开始
cycler = itertools.cycle(["A", "B", "C"])  # 无限循环A, B, C, A, B, C, ...
print("itertools.cycle示例(循环ABC):")
for i, char in enumerate(cycler):
    if i >= 6:  # 只显示前6个,否则会无限循环
        break
    print(char, end=" ")  # 输出: A B C A B C
print()

# repeat: 重复元素n次或无限次 - 简单地重复同一个值
repeater = itertools.repeat("Python", 3)  # 重复"Python"三次
print("itertools.repeat示例(重复Python 3次):")
for item in repeater:  # 这个迭代器会自动在3次后停止
    print(item, end=" ")  # 输出: Python Python Python
print("\n")

# 3.2 组合迭代器
print("3.2 组合迭代器:")

# chain: 连接多个迭代器 - 将多个迭代器首尾相连
print("itertools.chain示例(连接多个迭代器):")
# 连接三个不同类型的可迭代对象
combined = itertools.chain([1, 2], ["a", "b"], (True, False))
for item in combined:
    print(item, end=" ")  # 输出: 1 2 a b True False
print()

# zip_longest: 合并迭代器,可处理不等长情况
# 与内置zip不同,zip_longest会继续迭代到最长的迭代器结束
print("itertools.zip_longest示例(合并不等长迭代器):")
for item in itertools.zip_longest([1, 2], [3, 4, 5, 6], fillvalue="N/A"):
    # fillvalue指定短序列的填充值
    print(item)  # 输出: (1, 3), (2, 4), ('N/A', 5), ('N/A', 6)

# 3.3 过滤和映射
print("\n3.3 过滤和映射:")

# filter: 过滤元素 - 只保留满足条件的元素
print("filter示例(过滤偶数):")
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# lambda x: x % 2 == 0 是一个匿名函数,检查x是否为偶数
even_numbers = filter(lambda x: x % 2 == 0, numbers)
for num in even_numbers:
    print(num, end=" ")  # 输出: 2 4 6 8 10
print()

# map: 映射转换 - 对每个元素应用函数
print("map示例(平方运算):")
# lambda x: x**2 是一个匿名函数,计算x的平方
squared = map(lambda x: x**2, numbers)
for num in squared:
    print(num, end=" ")  # 输出: 1 4 9 16 25 36 49 64 81 100
print("\n")

# 3.4 排列组合迭代器
print("3.4 排列组合迭代器:")

# combinations: 返回指定长度的所有组合(不考虑顺序)
print("itertools.combinations示例(3选2组合):")
# 从[1,2,3]中选择2个元素的所有可能组合
for combo in itertools.combinations([1, 2, 3], 2):
    print(combo, end=" ")  # 输出: (1, 2) (1, 3) (2, 3)
print()

# permutations: 返回指定长度的所有排列(考虑顺序)
print("itertools.permutations示例(3选2排列):")
# 从[1,2,3]中选择2个元素的所有可能排列
for perm in itertools.permutations([1, 2, 3], 2):
    print(perm, end=" ")  # 输出: (1, 2) (1, 3) (2, 1) (2, 3) (3, 1) (3, 2)
print()

# product: 返回多个可迭代对象的笛卡尔积
print("itertools.product示例(笛卡尔积):")
# 计算"AB"和[1,2]的笛卡尔积(所有可能的组合)
for prod in itertools.product("AB", [1, 2]):
    print(prod, end=" ")  # 输出: ('A', 1) ('A', 2) ('B', 1) ('B', 2)
print("\n")


# 第四部分:迭代器与生成器的关系
print("=" * 50)
print("第四部分:迭代器与生成器的关系")
print("=" * 50)

print("\n生成器是一种特殊的迭代器,使用yield语句简化迭代器的创建")
print("生成器函数示例(等价于上面的Fibonacci类):")


def fibonacci_generator(limit):
    """使用生成器函数创建斐波那契数列

    这个函数使用yield语句,比上面的类实现更简洁
    yield会暂停函数执行并返回一个值,下次调用时从暂停处继续
    """
    a, b = 0, 1  # 初始化前两个数
    count = 0  # 计数器

    while count < limit:
        yield a  # yield暂停执行并返回值,保存当前状态
        a, b = b, a + b  # 更新状态
        count += 1  # 增加计数器


# 使用生成器
print("使用生成器的斐波那契数列:")
# 生成器函数调用时返回一个生成器对象,它是一个迭代器
for num in fibonacci_generator(10):  # 自动迭代
    print(num, end=" ")  # 输出: 0 1 1 2 3 5 8 13 21 34
print("\n")


# 第五部分:迭代器的实际应用
print("=" * 50)
print("第五部分:迭代器的实际应用")
print("=" * 50)

# 5.1 数据处理管道
print("\n5.1 数据处理管道:")
# 数据处理管道是迭代器的一个重要应用,可以分阶段处理数据


def data_source():
    """数据源 - 生成初始数据"""
    for i in range(1, 11):  # 生成1到10的数字
        yield i  # 一次返回一个数字


def process_data(data_iterator):
    """处理数据 - 对数据进行转换"""
    for item in data_iterator:  # 接收一个迭代器作为输入
        yield item * 10  # 将每个数字乘以10


def filter_data(data_iterator):
    """过滤数据 - 只保留符合条件的数据"""
    for item in data_iterator:  # 接收一个迭代器作为输入
        if item > 50:  # 只保留大于50的数字
            yield item  # 返回符合条件的数字


# 构建数据处理管道 - 将多个处理步骤连接起来
source = data_source()  # 创建数据源
processed = process_data(source)  # 处理数据
filtered = filter_data(processed)  # 过滤数据

print("数据处理管道结果:")
for result in filtered:  # 迭代最终结果
    print(result, end=" ")  # 输出: 60 70 80 90 100
print("\n")

# 5.2 内存高效的数据处理
print("5.2 内存高效的数据处理:")


def process_large_dataset(data):
    """处理大型数据集的示例

    这个函数展示了如何使用迭代器处理大型数据集,
    而不需要一次性将所有数据加载到内存中。
    """
    # 假设这是一个非常大的数据集
    # 使用迭代器可以一次只处理一个元素,不必全部加载到内存

    # 1. 过滤数据 - 只保留正数
    filtered_data = filter(lambda x: x > 0, data)

    # 2. 转换数据 - 将每个数字乘以2
    transformed_data = map(lambda x: x * 2, filtered_data)

    # 3. 限制结果数量 - 只取前5个结果
    limited_data = itertools.islice(transformed_data, 5)

    return limited_data  # 返回处理后的迭代器


# 模拟大数据集
sample_data = [-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
results = process_large_dataset(sample_data)

print("大数据处理结果:")
for result in results:  # 迭代处理结果
    print(result, end=" ")  # 输出: 2 4 6 8 10
print("\n")

# 5.3 自定义迭代器实际应用
print("5.3 自定义迭代器实际应用:")


class DateRange:
    """日期范围迭代器

    这个迭代器生成两个日期之间的所有日期。
    它展示了如何创建一个实用的自定义迭代器。
    """

    from datetime import datetime, timedelta

    def __init__(self, start_date, end_date):
        """初始化日期范围

        参数:
            start_date: 开始日期
            end_date: 结束日期
        """
        self.start_date = start_date  # 保存开始日期
        self.end_date = end_date  # 保存结束日期
        self.current_date = start_date  # 当前日期,初始为开始日期

    def __iter__(self):
        """返回迭代器自身"""
        self.current_date = self.start_date  # 重置当前日期
        return self

    def __next__(self):
        """返回下一个日期"""
        if self.current_date > self.end_date:
            # 如果当前日期超过结束日期,停止迭代
            raise StopIteration

        today = self.current_date  # 保存当前日期
        self.current_date += self.timedelta(days=1)  # 增加一天
        return today.strftime("%Y-%m-%d")  # 返回格式化的日期字符串


# 使用日期范围迭代器
from datetime import datetime, timedelta

start = datetime(2023, 1, 1)  # 开始日期:2023年1月1日
end = datetime(2023, 1, 5)  # 结束日期:2023年1月5日
date_range = DateRange(start, end)  # 创建日期范围迭代器

print("日期范围:")
for date in date_range:  # 迭代日期范围
    print(date)  # 输出每一天的日期


# 总结
print("\n" + "=" * 50)
print("迭代器总结")
print("=" * 50)

print(
    """
1. 迭代器核心特点:
   - 实现了__iter__()和__next__()方法
   - 惰性计算,按需生成数据
   - 只能向前迭代,不能回退
   - 迭代完成后抛出StopIteration异常

2. 迭代器的优势:
   - 内存效率高,适合处理大数据集
   - 支持无限序列
   - 可组合构建数据处理管道
   - 延迟计算,提高性能

3. 常用迭代器工具:
   - 内置函数: iter(), next()
   - itertools模块: count(), cycle(), chain()等
   - 函数式工具: map(), filter()

4. 最佳实践:
   - 使用生成器简化迭代器创建
   - 组合使用itertools提高效率
   - 构建处理管道提高代码可读性
   - 利用迭代器协议实现自定义集合类
"""
)

print("\n迭代器是Python中非常强大的工具,掌握它可以编写更高效、更优雅的代码!")


打印结果

==================================================
第一部分:迭代器基础概念
==================================================

1.1 可迭代对象与迭代器的区别:
可迭代对象: 实现了__iter__()方法,可以返回迭代器
迭代器: 实现了__iter__()和__next__()方法,可以逐个返回元素

1.2 内置可迭代对象示例:
列表是可迭代的: True
字典是可迭代的: True
集合是可迭代的: True
元组是可迭代的: True
字符串是可迭代的: True

1.3 获取迭代器并使用:
迭代器类型: <class 'list_iterator'>
第一个元素: 1
第二个元素: 2
第三个元素: 3

迭代器耗尽示例:
第四个元素: 4
第五个元素: 5
迭代器已耗尽,抛出StopIteration异常

==================================================
第二部分:创建自定义迭代器
==================================================

2.1 基本迭代器类:
倒计时:
5 4 3 2 1 

2.2 斐波那契数列迭代器:
斐波那契数列前10项:
0 1 1 2 3 5 8 13 21 34 

==================================================
第三部分:迭代器的高级用法
==================================================

3.1 无限迭代器:
itertools.count示例(从10开始,步长为2):
10 12 14 16 18 
itertools.cycle示例(循环ABC):
A B C A B C 
itertools.repeat示例(重复Python 3次):
Python Python Python 

3.2 组合迭代器:
itertools.chain示例(连接多个迭代器):
1 2 a b True False 
itertools.zip_longest示例(合并不等长迭代器):
(1, 3)
(2, 4)
('N/A', 5)
('N/A', 6)

3.3 过滤和映射:
filter示例(过滤偶数):
2 4 6 8 10 
map示例(平方运算):
1 4 9 16 25 36 49 64 81 100 

3.4 排列组合迭代器:
itertools.combinations示例(3选2组合):
(1, 2) (1, 3) (2, 3) 
itertools.permutations示例(3选2排列):
(1, 2) (1, 3) (2, 1) (2, 3) (3, 1) (3, 2) 
itertools.product示例(笛卡尔积):
('A', 1) ('A', 2) ('B', 1) ('B', 2) 

==================================================
第四部分:迭代器与生成器的关系
==================================================

生成器是一种特殊的迭代器,使用yield语句简化迭代器的创建
生成器函数示例(等价于上面的Fibonacci类):
使用生成器的斐波那契数列:
0 1 1 2 3 5 8 13 21 34 

==================================================
第五部分:迭代器的实际应用
==================================================

5.1 数据处理管道:
数据处理管道结果:
60 70 80 90 100 

5.2 内存高效的数据处理:
大数据处理结果:
2 4 6 8 10 

5.3 自定义迭代器实际应用:
日期范围:
2023-01-01
2023-01-02
2023-01-03
2023-01-04
2023-01-05

==================================================
迭代器总结
==================================================

1. 迭代器核心特点:
   - 实现了__iter__()和__next__()方法
   - 惰性计算,按需生成数据
   - 只能向前迭代,不能回退
   - 迭代完成后抛出StopIteration异常

2. 迭代器的优势:
   - 内存效率高,适合处理大数据集
   - 支持无限序列
   - 可组合构建数据处理管道
   - 延迟计算,提高性能

3. 常用迭代器工具:
   - 内置函数: iter(), next()
   - itertools模块: count(), cycle(), chain()等
   - 函数式工具: map(), filter()

4. 最佳实践:
   - 使用生成器简化迭代器创建
   - 组合使用itertools提高效率
   - 构建处理管道提高代码可读性
   - 利用迭代器协议实现自定义集合类


迭代器是Python中非常强大的工具,掌握它可以编写更高效、更优雅的代码!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值