一、可迭代对象

在 Python 中,我们把能够使用for循环进行遍历的对象,统称为可迭代对象。它是迭代机制的基础载体,是我们最常接触的数据类型。

1. 可迭代对象的常见类型

Python 中内置的容器类型绝大多数都是可迭代对象,主要包括:列表 (list)、元组 (tuple)、字符

串 (str)、字典 (dict)、集合 (set)、生成器 (generator) 等。

2. 可迭代对象的核心特征

可迭代对象的本质是实现了__iter__()方法的对象。当我们对一个可迭代对象使用iter()函数时,Python 会自动调用其内部的__iter__()方法,将其转换为迭代器,这是可迭代对象与迭代器之间转换的桥梁。

简单来说:可迭代对象只具备 "可被遍历" 的能力,但不具备直接逐个获取元素的能力,必须转换为迭代器才能实现

二、迭代器

迭代器是Python迭代机制的执行核心,它是由可迭代对象转换而来的特殊对象,具备惰性取值、一次性遍历的核心特性。

1. 迭代器的创建

我们可以通过Python内置函数iter(),将可迭代对象转换为迭代器,这是迭代器最常用的创建方式:

list_1 = [1, 2, 3, 4, 5, 6] 
# 调用iter()函数,将列表转换为迭代器 
iterator = iter(list_1) 

2. 迭代器的iter()和next()方法

迭代器依赖两个核心方法实现迭代功能:iter()next()

iter():将可迭代对象转换为迭代器;

next():逐个获取迭代器中的元素,每调用一次,就返回下一个元素。

代码示例:

list_1 = [1, 2, 3, 4, 5, 6]
# 将可迭代对象转换为迭代器
iterator = iter(list_1)
# 使用next()逐个取值
print(next(iterator)) # 输出:1
print(next(iterator)) # 输出:2
print(next(iterator)) # 输出:3

3. 迭代器的一次性遍历

迭代器最大的特点是只能遍历一次,元素会被消耗。当我们使用next()for循环遍历完迭代器的所有元素后,迭代器就会清空,无法再次遍历。

list_1 = [1, 2, 3, 4, 5, 6]
# 将可迭代对象转换为迭代器
iterator = iter(list_1)

# 使用next()逐个取值
print(next(iterator)) # 输出:1
print(next(iterator)) # 输出:2
print(next(iterator)) # 输出:3

print("*"*20)
# for循环遍历迭代器,只会输出未被next()读取的剩余元素
for item in iterator:
    print(item) # 输出:4、5、6

程序运行结果

原因:迭代器是惰性序列,它不会在内存中存储所有元素,而是在调用next()时才计算并返回下一个元素,元素被取出后就会被释放,因此无法重复遍历

4. for循环遍历迭代器的原理

我们使用for循环遍历迭代器时,Python底层自动完成了三步操作:

        调用iter()函数获取迭代器对象;

        循环调用next()函数逐个获取元素;

        捕获StopIteration异常,自动结束循环。

这也是for循环能遍历所有可迭代对象的底层逻辑。

5. 可迭代和迭代器的判断

Python提供了collections.abc模块,判断对象类型:

from collections.abc import Iterator, Iterable 
# 判断列表是否为迭代器:
print(isinstance([], Iterator))   # 输出False
# 判断列表是否为可迭代对象:
print(isinstance([], Iterable))   # 输出True

三、生成器:特殊的迭代器

生成器是 Python 中自带迭代器功能的特殊对象,是迭代器的子集,也是 Python 实现惰性计算的最佳工具。

1. 生成器的定义

生成器的核心是yield关键字:在函数中使用yield替代return返回数据,这个函数就不再是普通函数,而是生成器函数,调用后会返回生成器对象。

# 定义生成器函数
def gen_func():
    yield 1
    yield 2
    yield 3

# 创建生成器对象
gen = gen_func()

2. 生成器的核心特性

生成器对象本质就是迭代器对象,它完全具备迭代器的所有特性:支持next()取值、支持for循环遍历、一次性消耗、惰性计算。

# 定义生成器函数
def gen_func():
    yield 1
    yield 2
    yield 3

# 创建生成器对象
gen = gen_func()

# 生成器可以直接使用next()
print(next(gen))  # 输出:1
# 生成器可以用for循环遍历
for item in gen:
    print(item)   # 输出:2 3

普通迭代器需要基于可迭代对象创建,而生成器可以自定义迭代逻辑,不需要提前创建数据序列。

4. 创建生成器

(1)生成器函数(用 yield 关键字)

普通函数里,把return换成yield,这个函数就变成生成器函数;调用函数不会执行代码,而是返回一个生成器对象。

可以多次yield,暂停保存状态,按需产出数据,适合逻辑复杂、多步骤的场景。

(2)生成器表达式

与列表推导式语法几乎一致,唯一区别是将列表推导式的[](方括号)改为()(圆括号)。

一行代码就能实现,适合逻辑简单、无需复杂步骤的场景。

5. 生成器表达式与列表推导式的对比

生成器表达式与列表推导式外观相似,但在内存占用、取值特性等核心维度差异显著,具体区别如下:

(1)语法

  • 列表推导式:用 []方括号包裹,例如 [i for i in range(10)]

  • 生成器表达式:用 () 圆括号包裹,例如 (i for i in range(10))

(2)内存 

  • 列表推导式:一次性把所有元素全部创建并存入内存,处理大了数据时会占用极高的内存,甚至导致程序卡顿、内存溢出;

  • 生成器表达式:采用“惰性加载”机制,只保存生成数据,不需要提前创建任何元素,用一个算一个,全程几乎不占用内存。

(3)取值

  • 列表推导式:生成的列表是可迭代对象,支持重复取值、索引、切片操作,可多次用for循环遍历;

    list_1 = [i for i in range( 5 )]
    print( list_1[2] )  # 支持索引,输出:2
  • 生成器表达式:生成的生成器是迭代器,只能一次性消耗,遍历完后元素全部清空;不支持索引、切片操作,再次遍历无任何输出。

    gen_temp = (i for i in range(5))
    # print(gen_comp[2]) # 直接报错,不支持索引
    
    for num in gen_temp:
        # 第一次遍历消耗全部元素 输出 0 1 2 3 4
        print(num)
    
    for num in gen_temp:
        # 第二次遍历无任何输出
        print(num)

(4)类型

  • 列表推导式 → 生成 list类型,只是可迭代对象,不是迭代器;

  • 生成器表达式 → 生成 generator 类型,本身就是迭代器,具备迭代器的所有特性。

    from collections.abc import Iterator
    list_temp = [i for i in range(5)]
    gen_temp = (i for i in range(5))
    
    print(isinstance(list_temp, Iterator))  # 输出 False
    print(isinstance(gen_temp, Iterator))  # 输出 True

四、为什么需要迭代器

迭代器是 Python 的核心设计之一,它的存在解决了两大关键问题:

1. 节省内存,高效处理海量数据

列表、元组等可迭代对象会一次性将所有元素加载到内存中,当处理百万、千万级海量数据时,会极大占用内存资源。而迭代器是惰性计算:只有在需要取值时才生成元素,全程只占用一个元素的内存空间,极大提升了程序的内存利用率。

2. 统一遍历规则,简化代码逻辑

Python 中有列表、字符串、字典等多种可迭代容器,它们的内部结构完全不同,但迭代器为所有容器提供了统一的遍历接口。我们无需关心容器的底层结构,只需要使用iter()next(),就能实现统一遍历,大幅降低了编程的复杂度。

五、总结

  • 可迭代对象:可通过 for 循环遍历,核心是实现__iter__() 方法,常见类型有列表、元组等,需通过 iter () 函数转换为迭代器才能逐个取值。
  • 迭代器:由可迭代对象通过 iter () 创建,依赖 iter () 和 next () 方法,具备惰性取值、一次性遍历特性,for 循环遍历其底层是自动获取迭代器、调用 next () 并捕获异常。可通过 isinstance () 结合 Iterator、Iterable 判断类型。
  • 生成器:特殊的迭代器,核心是 yield 关键字,有生成器函数(多 yield、适合复杂逻辑)和生成器表达式(() 包裹、适合简单逻辑)两种写法;与列表推导式在语法、内存、取值、类型上差异显著。
  • 迭代器的作用:解决海量数据内存占用问题,统一各类可迭代容器的遍历规则,简化编程逻辑。

更多推荐