普通视图

发现新文章,点击刷新页面。
昨天 — 2025年5月21日首页

Python迭代器与生成器全解析:让你的代码高效又优雅!

作者 烛阴
2025年5月21日 22:43

一、什么是迭代器(Iterator)?

1.1 迭代器的定义

迭代器是一个可以记住遍历位置的对象。它实现了两个方法:__iter__()__next__()
任何实现了这两个方法的对象都可以称为迭代器。

1.2 为什么需要迭代器?

  • 节省内存:不需要一次性加载所有数据
  • 惰性计算:按需生成数据,适合处理大数据集
  • 代码简洁:统一的遍历接口

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

  • 可迭代对象(Iterable):实现了__iter__()方法,如list、tuple、dict、str等
  • 迭代器(Iterator):实现了__iter__()__next__()方法

1.4 例子:for循环的本质

nums = [1, 2, 3]
it = iter(nums)  # 获取迭代器
print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3
# print(next(it))  # StopIteration异常

二、自定义迭代器

2.1 实现一个自定义迭代器

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

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < self.end:
            num = self.current
            self.current += 1
            return num
        else:
            raise StopIteration

for i in MyRange(1, 4):
    print(i)  # 输出 1 2 3

三、生成器(Generator)

3.1 生成器的定义

在 Python 中,使用了 yield 的函数被称为生成器(generator)。 生成器是一种特殊的迭代器,用于生成序列。它更简单、更强大,使用yield语句返回数据。

3.2 生成器函数

def my_generator():
    yield 1
    yield 2
    yield 3

for value in my_generator():
    print(value)  # 输出 1 2 3

3.3 生成器表达式

gen = (x * x for x in range(3))
for num in gen:
    print(num)  # 输出 0 1 4

四、生成器的高级用法

4.1 惰性求值与大数据处理

生成器不会一次性生成所有数据,而是每次请求时才生成下一个值,非常适合处理大文件或无限序列。

def read_large_file(file_path):
    with open(file_path) as f:
        for line in f:
            yield line.strip()

4.2 生成器的send()throw()close()

生成器不仅可以next(),还可以通过send()向生成器内部传值。

def echo():
    received = yield "start"
    while True:
        received = yield received

gen = echo()
print(next(gen))         # 输出 start
print(gen.send("hello")) # 输出 hello
print(gen.send("world")) # 输出 world

五、迭代器与生成器的最佳实践

5.1 用生成器处理大数据

def count_up_to(n):
    count = 1
    while count <= n:
        yield count
        count += 1

for num in count_up_to(1000000):
    pass  # 不会占用太多内存,因为每次只生成一个数字

5.2 组合生成器

def gen1():
    yield from range(3)

def gen2():
    yield from gen1()
    yield 100

for i in gen2():
    print(i)  # 输出 0 1 2 100

5.3 反向迭代

list1 = [1,2,3,4,5]
for num1 in reversed(list1) : # Python 中有内置的函数 `reversed()`
    print ( num1 , end = ' ' )

注意:反向迭代仅仅当对象的大小可预先确定或者对象实现了 __reversed__() 的特殊方法时才能生效。 如果两者都不符合,那你必须先将对象转换为一个列表才行

5.4 同时迭代多个序列

names = ['laingdianshui', 'twowater', '两点水']
ages = [18, 19, 20]
for name, age in zip(names, ages): # 
     print(name,age)

注意:zip(a, b) 会生成一个可返回元组 (x, y) 的迭代器,其中 x 来自 a,y 来自 b。 一旦其中某个序列到底结尾,迭代宣告结束。 因此迭代长度跟参数中最短序列长度一致


六、常见误区与注意事项

  • 生成器只能遍历一次,遍历完后就“耗尽”了
  • 不要滥用生成器表达式,复杂逻辑建议用生成器函数
  • StopIteration异常是生成器和迭代器结束的标志

最后

如果你觉得这篇文章有用,记得点赞、关注、收藏,学Python更轻松!!

❌
❌