ITPub博客

首页 > 应用开发 > Python > 人工智能之编程基础 Python 入门:第七章 迭代器与生成器

人工智能之编程基础 Python 入门:第七章 迭代器与生成器

原创 Python 作者:咚咚王者 时间:2025-11-17 19:33:15 0 删除 编辑

人工智能之编程基础 Python 入门

第七章 迭代器与生成器



前言

经过对基本数据的学习,本章主要是对数据中的元素的遍历与生成的学习,大周末好好看好好学。未来就在你们的手中。


迭代器

在 Python 中, 迭代器(Iterator) 是一种设计模式,也是一种对象,它允许你遍历一个容器(如列表、字典、集合等)中的所有元素,而无需了解其内部结构。


1. 什么是迭代器?

迭代器是一个实现了 迭代器协议的对象,该协议包含两个方法:

  • __iter__():返回迭代器对象本身
  • __next__():返回容器中的下一个元素,如果没有更多元素则抛出  StopIteration 异常

2. 迭代器的工作原理

Python 的  for 循环、列表推导式等都依赖于迭代器协议:

# for 循环的底层工作方式my_list = [1, 2, 3]# 1. 获取迭代器iterator = iter(my_list)  # 调用 my_list.__iter__()# 2. 重复调用 next()try:    while True:
        element = next(iterator)  # 调用 iterator.__next__()
        print(element)except StopIteration:    pass  # 遍历结束

3. 创建迭代器

方法 1:使用内置类型的迭代器

# 列表的迭代器my_list = [1, 2, 3]
list_iter = iter(my_list)print(next(list_iter))  # 1print(next(list_iter))  # 2print(next(list_iter))  # 3# print(next(list_iter))  # StopIteration 异常

方法 2:自定义迭代器类

class CountDown:    def __init__(self, start):
        self.start = start    
    def __iter__(self):        return self    
    def __next__(self):        if self.start <= 0:            raise StopIteration
        self.start -= 1
        return self.start + 1# 使用自定义迭代器countdown = CountDown(3)for num in countdown:    print(num)  # 输出: 3, 2, 1

4. 可迭代对象 vs 迭代器

这两个概念经常被混淆:

概念 说明 示例
可迭代对象 (Iterable) 实现了  __iter__() 方法的对象,可以被  for 循环遍历 list, str, dict, set, tuple
迭代器 (Iterator) 实现了  __iter__() 和  __next__() 方法的对象,是遍历的执行者 list_iterator, dict_keyiterator, 生成器
my_list = [1, 2, 3]# my_list 是可迭代对象print(hasattr(my_list, '__iter__'))  # True# 获取迭代器iterator = iter(my_list)print(hasattr(iterator, '__next__'))  # Trueprint(hasattr(iterator, '__iter__'))  # True

关键点:所有迭代器都是可迭代的,但并非所有可迭代对象都是迭代器。


5. 内置的迭代器工具

Python 的  itertools 模块提供了强大的迭代器工具:

import itertools# 无限迭代器counter = itertools.count(1)  # 1, 2, 3, ...repeater = itertools.repeat("hello", 3)  # 'hello', 'hello', 'hello'# 组合迭代器numbers = [1, 2, 3]print(list(itertools.permutations(numbers, 2)))  # [(1,2), (1,3), (2,1), ...]print(list(itertools.combinations(numbers, 2)))  # [(1,2), (1,3), (2,3)]# 其他工具print(list(itertools.chain([1,2], [3,4])))        # [1, 2, 3, 4]print(list(itertools.islice(range(10), 5)))       # [0, 1, 2, 3, 4]

6. 迭代器的"耗尽"特性

迭代器只能遍历一次,遍历完成后就会"耗尽"。

my_list = [1, 2, 3]
iterator = iter(my_list)# 第一次遍历print(list(iterator))  # [1, 2, 3]# 第二次遍历print(list(iterator))  # [] 空!迭代器已经耗尽# 解决方案:重新创建迭代器iterator = iter(my_list)print(list(iterator))  # [1, 2, 3]

生成器

在 Python 中, 生成器(Generator) 是一种特殊的 迭代器,它能以一种简洁、内存高效的方式生成一系列值。生成器的核心是 惰性求值——只在需要时才计算下一个值。


1. 生成器的本质

生成器是实现了 迭代器协议的函数或表达式,具有以下特点:

  • 惰性求值:不一次性生成所有值
  • 状态保持:函数执行到  yield 时暂停,保留当前状态
  • 内存友好:只存储当前值,适合处理大数据集
  • 单次遍历:生成器只能遍历一次

2. 创建生成器的两种方式

方式 1:生成器函数(使用  yield)

def count_up_to(max_num):    """生成从1到max_num的数字"""
    count = 1
    while count <= max_num:        yield count  # 暂停并返回值
        count += 1# 使用生成器counter = count_up_to(3)print(type(counter))  # <class 'generator'># 可以用 for 循环遍历for num in counter:    print(num)  # 输出: 1, 2, 3# 或者用 next() 逐个获取counter = count_up_to(3)  # 需要重新创建print(next(counter))  # 1print(next(counter))  # 2print(next(counter))  # 3# print(next(counter))  # StopIteration 异常

方式 2:生成器表达式

# 语法类似列表推导式,但使用圆括号squares_gen = (x**2 for x in range(5))print(type(squares_gen))  # <class 'generator'># 遍历生成器for sq in squares_gen:    print(sq)  # 0, 1, 4, 9, 16# 与列表推导式的对比squares_list = [x**2 for x in range(5)]  # 立即创建整个列表squares_gen = (x**2 for x in range(5))    # 惰性求值,按需计算

3.  yield 关键字的工作原理

yield 是生成器的核心,它的工作方式:

  1. 当函数遇到  yield 时,返回一个值并 暂停执行
  2. 保留函数的所有局部变量和执行状态
  3. 下次调用  next() 时,从暂停处继续执行
  4. 直到函数结束或遇到  return,抛出  StopIteration
def simple_generator():    print("开始")    yield 1
    print("第一次暂停后")    yield 2
    print("第二次暂停后")    yield 3
    print("结束")
gen = simple_generator()print(next(gen))  # 开始\n1print(next(gen))  # 第一次暂停后\n2print(next(gen))  # 第二次暂停后\n3# print(next(gen))  # 结束\nStopIteration

4. 生成器的高级特性

1.  yield from - 委托生成器

def sub_generator():    yield "a"
    yield "b"def main_generator():    yield 1
    yield from sub_generator()  # 委托给另一个生成器
    yield 2for item in main_generator():    print(item)  # 1, 'a', 'b', 2

2. 生成器的  send() 方法

def echo_generator():    while True:
        received = yield  # 接收外部发送的值
        print(f"收到: {received}")
gen = echo_generator()next(gen)  # 启动生成器gen.send("Hello")   # 收到: Hellogen.send("World")   # 收到: World

3.  throw() 和  close()

gen = count_up_to(5)print(next(gen))  # 1gen.throw(ValueError("手动抛出异常"))  # 在生成器内部引发异常# 或者gen = count_up_to(5)
gen.close()  # 关闭生成器,后续调用会抛出 StopIteration

5. 生成器 vs 列表

特性 生成器 列表
内存使用 极低(只存当前值) 高(存储所有值)
创建速度 快(立即返回) 慢(需计算所有值)
访问方式 顺序访问,只能遍历一次 随机访问,可多次遍历
适用场景 大数据流、无限序列 小数据集、需要索引访问
# 处理大文件 - 生成器版本def read_file_lines(filename):    with open(filename) as f:        for line in f:            yield line.strip()# 只占用一行的内存for line in read_file_lines("huge_file.txt"):
    process(line)# 列表版本 - 会加载整个文件到内存lines = [line.strip() for line in open("huge_file.txt")]

6. 生成器的"耗尽"特性

生成器只能遍历一次,遍历完成后就会耗尽:

gen = (x for x in range(3))print(list(gen))  # [0, 1, 2]print(list(gen))  # [] 空!生成器已耗尽# 解决方案:重新创建gen = (x for x in range(3))print(list(gen))  # [0, 1, 2]

实际应用示例

1. 斐波那契数列

def fibonacci():
    a, b = 0, 1
    while True:        yield a
        a, b = b, a + b# 获取前10个斐波那契数fib = fibonacci()
first_10 = [next(fib) for _ in range(10)]print(first_10)  # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

2. 数据处理管道

def process_numbers():    # 原始数据
    numbers = range(1, 101)    
    # 过滤偶数
    evens = (n for n in numbers if n % 2 == 0)    
    # 计算平方
    squares = (n**2 for n in evens)    
    # 只取前10个
    return itertools.islice(squares, 10)
result = list(process_numbers())print(result)  # [4, 16, 36, 64, 100, 144, 196, 256, 324, 400]

3. 无限序列

def natural_numbers(start=1):    while True:        yield start
        start += 1# 只计算需要的值first_5 = list(itertools.islice(natural_numbers(), 5))

4. 树的遍历

class TreeNode:    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right    
    def inorder(self):        """中序遍历生成器"""
        if self.left:            yield from self.left.inorder()        yield self.value        if self.right:            yield from self.right.inorder()# 使用root = TreeNode(2, TreeNode(1), TreeNode(3))for val in root.inorder():    print(val)  # 1, 2, 3

何时使用生成器?

✅  适合使用生成器的场景:

  • 处理大型数据集(文件、数据库查询结果)
  • 无限序列(自然数、时间序列)
  • 数据管道处理(过滤、转换、聚合)
  • 内存敏感的应用
  • 需要惰性求值的场景

❌  不适合使用生成器的场景:

  • 需要随机访问元素
  • 需要多次遍历数据
  • 数据量很小
  • 需要索引操作

总结

本文主要对遍历集合元素的两种访问方式即迭代器与生成器的学习。了解掌握他们的特性有助于在实际应用中提高访问效率。

资料关注

相关资料获取:
公众号:咚咚王

艺术二维码.png

《Python 编程:从入门到实践》
《利用 Python 进行数据分析》
《算法导论中文第三版》
《概率论与数理统计(第四版) (盛骤) 》
《程序员的数学》
《线性代数应该这样学第 3 版》
《微积分和数学分析引论》
《(西瓜书)周志华-机器学习》
《TensorFlow 机器学习实战指南》
《Sklearn 与 TensorFlow 机器学习实用指南》
《模式识别(第四版)》
《深度学习 deep learning》伊恩·古德费洛著 花书
《Python 深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》
《深入浅出神经网络与深度学习 +(迈克尔·尼尔森(Michael+Nielsen) 》
《自然语言处理综论 第 2 版》
《Natural-Language-Processing-with-PyTorch》
《计算机视觉-算法与应用(中文版)》
《Learning OpenCV 4》
《AIGC:智能创作时代》杜雨 +&+ 张孜铭
《AIGC 原理与实践:零基础学大语言模型、扩散模型和多模态模型》
《从零构建大语言模型(中文版)》
《实战 AI 大模型》
《AI 3.0》


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048224/viewspace-3102013/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
深耕人工智能领域,做你的随身笔记。

注册时间:2025-10-26

  • 博文量
    47
  • 访问量
    46030