首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >人工智能之编程基础 Python 入门:第七章 迭代器与生成器

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

原创
作者头像
咚咚王
修改2025-11-17 20:10:55
修改2025-11-17 20:10:55
1080
举报

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

第七章 迭代器与生成器


前言

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


迭代器

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


1. 什么是迭代器?

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

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

2. 迭代器的工作原理

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

代码语言:python
复制
# 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:使用内置类型的迭代器

代码语言:python
复制
# 列表的迭代器
my_list = [1, 2, 3]
list_iter = iter(my_list)

print(next(list_iter))  # 1
print(next(list_iter))  # 2
print(next(list_iter))  # 3
# print(next(list_iter))  # StopIteration 异常

方法 2:自定义迭代器类

代码语言:python
复制
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, 生成器

代码语言:python
复制
my_list = [1, 2, 3]

# my_list 是可迭代对象
print(hasattr(my_list, '__iter__'))  # True

# 获取迭代器
iterator = iter(my_list)
print(hasattr(iterator, '__next__'))  # True
print(hasattr(iterator, '__iter__'))  # True

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


5. 内置的迭代器工具

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

代码语言:python
复制
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. 迭代器的"耗尽"特性

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

代码语言:python
复制
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

代码语言:python
复制
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))  # 1
print(next(counter))  # 2
print(next(counter))  # 3
# print(next(counter))  # StopIteration 异常

方式 2:生成器表达式

代码语言:python
复制
# 语法类似列表推导式,但使用圆括号
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
代码语言:python
复制
def simple_generator():
    print("开始")
    yield 1
    print("第一次暂停后")
    yield 2
    print("第二次暂停后")
    yield 3
    print("结束")

gen = simple_generator()

print(next(gen))  # 开始\n1
print(next(gen))  # 第一次暂停后\n2
print(next(gen))  # 第二次暂停后\n3
# print(next(gen))  # 结束\nStopIteration

4. 生成器的高级特性

1. yield from - 委托生成器

代码语言:python
复制
def sub_generator():
    yield "a"
    yield "b"

def main_generator():
    yield 1
    yield from sub_generator()  # 委托给另一个生成器
    yield 2

for item in main_generator():
    print(item)  # 1, 'a', 'b', 2

2. 生成器的 send() 方法

代码语言:python
复制
def echo_generator():
    while True:
        received = yield  # 接收外部发送的值
        print(f"收到: {received}")

gen = echo_generator()
next(gen)  # 启动生成器

gen.send("Hello")   # 收到: Hello
gen.send("World")   # 收到: World

3. throw()close()

代码语言:python
复制
gen = count_up_to(5)

print(next(gen))  # 1
gen.throw(ValueError("手动抛出异常"))  # 在生成器内部引发异常

# 或者
gen = count_up_to(5)
gen.close()  # 关闭生成器,后续调用会抛出 StopIteration

5. 生成器 vs 列表

特性

生成器

列表

内存使用

极低(只存当前值)

高(存储所有值)

创建速度

快(立即返回)

慢(需计算所有值)

访问方式

顺序访问,只能遍历一次

随机访问,可多次遍历

适用场景

大数据流、无限序列

小数据集、需要索引访问

代码语言:python
复制
# 处理大文件 - 生成器版本
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. 生成器的"耗尽"特性

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

代码语言:python
复制
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. 斐波那契数列

代码语言:python
复制
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. 数据处理管道

代码语言:python
复制
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. 无限序列

代码语言:python
复制
def natural_numbers(start=1):
    while True:
        yield start
        start += 1

# 只计算需要的值
first_5 = list(itertools.islice(natural_numbers(), 5))

4. 树的遍历

代码语言:python
复制
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

何时使用生成器?

适合使用生成器的场景:

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

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

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

总结

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

资料关注

公众号:咚咚王

《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》

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 人工智能之编程基础 Python 入门
  • 前言
  • 迭代器
    • 1. 什么是迭代器?
    • 2. 迭代器的工作原理
    • 3. 创建迭代器
      • 方法 1:使用内置类型的迭代器
      • 方法 2:自定义迭代器类
    • 4. 可迭代对象 vs 迭代器
    • 5. 内置的迭代器工具
    • 6. 迭代器的"耗尽"特性
  • 生成器
    • 1. 生成器的本质
    • 2. 创建生成器的两种方式
      • 方式 1:生成器函数(使用 yield)
      • 方式 2:生成器表达式
    • 3. yield 关键字的工作原理
    • 4. 生成器的高级特性
      • 1. yield from - 委托生成器
      • 2. 生成器的 send() 方法
      • 3. throw() 和 close()
    • 5. 生成器 vs 列表
    • 6. 生成器的"耗尽"特性
  • 实际应用示例
    • 1. 斐波那契数列
    • 2. 数据处理管道
    • 3. 无限序列
    • 4. 树的遍历
  • 何时使用生成器?
  • 总结
  • 资料关注
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档