← 返回首页
🐍

可迭代对象与迭代器

📂 python ⏱ 2 min 384 words

什么是可迭代对象

可迭代对象是实现了__iter__方法的对象,它可以被for循环遍历。

# 常见的可迭代对象
numbers = [1, 2, 3]          # 列表
text = "Hello"               # 字符串
data = (1, 2, 3)             # 元组
unique = {1, 2, 3}           # 集合
mapping = {'a': 1, 'b': 2}   # 字典

# 检查是否可迭代
from collections.abc import Iterable, Iterator

print(isinstance(numbers, Iterable))  # 输出: True
print(isinstance(numbers, Iterator))  # 输出: False

迭代协议

迭代协议定义了对象如何被迭代,需要实现__iter____next__方法。

class NumberRange:
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.start >= self.end:
            raise StopIteration
        current = self.start
        self.start += 1
        return current

# 使用自定义迭代器
numbers = NumberRange(1, 5)
for num in numbers:
    print(num, end=" ")  # 输出: 1 2 3 4

迭代器与可迭代对象的区别

可迭代对象可以被多次迭代,而迭代器是一次性的。

# 可迭代对象可以多次使用
my_list = [1, 2, 3]
print(list(my_list))  # 输出: [1, 2, 3]
print(list(my_list))  # 输出: [1, 2, 3]  # 可以再次使用

# 迭代器只能使用一次
my_iter = iter([1, 2, 3])
print(list(my_iter))  # 输出: [1, 2, 3]
print(list(my_iter))  # 输出: []  # 已经耗尽

# 手动使用迭代器
my_iter = iter([10, 20, 30])
print(next(my_iter))  # 输出: 10
print(next(my_iter))  # 输出: 20
print(next(my_iter))  # 输出: 30

自定义迭代器

创建自定义迭代器需要实现迭代协议的两个方法。

class Fibonacci:
    def __init__(self, max_count):
        self.max_count = max_count
        self.count = 0
        self.a = 0
        self.b = 1

    def __iter__(self):
        return self

    def __next__(self):
        if self.count >= self.max_count:
            raise StopIteration
        result = self.a
        self.a, self.b = self.b, self.a + self.b
        self.count += 1
        return result

# 使用斐波那契迭代器
fib = Fibonacci(10)
for num in fib:
    print(num, end=" ")  # 输出: 0 1 1 2 3 5 8 13 21 34

生成器函数

生成器函数使用yield语句创建迭代器,代码更简洁。

def countdown(n):
    while n > 0:
        yield n
        n -= 1

# 使用生成器
for i in countdown(5):
    print(i, end=" ")  # 输出: 5 4 3 2 1

# 生成器表达式
squares = (x**2 for x in range(10))
print(list(squares))  # 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

itertools模块

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

import itertools

# 无限计数器
counter = itertools.count(1, 2)  # 从1开始,步长2
print([next(counter) for _ in range(5)])  # 输出: [1, 3, 5, 7, 9]

# 无限循环
colors = itertools.cycle(['红', '绿', '蓝'])
print([next(colors) for _ in range(6)])  # 输出: ['红', '绿', '蓝', '红', '绿', '蓝']

# 组合
items = ['A', 'B', 'C']
print(list(itertools.combinations(items, 2)))  # 输出: [('A', 'B'), ('A', 'C'), ('B', 'C')]

# 排列
print(list(itertools.permutations(items, 2)))
# 输出: [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]

迭代器的内存优势

迭代器采用惰性求值,一次只处理一个元素,节省内存。

# 列表方式(占用大量内存)
def get_squares_list(n):
    return [x**2 for x in range(n)]

# 迭代器方式(内存友好)
def get_squares_iter(n):
    for x in range(n):
        yield x**2

# 处理大数据时,迭代器更高效
large_number = 1000000

# 这会占用大量内存
# squares_list = get_squares_list(large_number)

# 这不会一次性占用大量内存
for square in get_squares_iter(large_number):
    if square > 100:
        break
    print(square, end=" ")

最佳实践

掌握迭代器和生成器是编写高效Python代码的关键技能。