Python基础学习教程:迭代器和生成器

迭代器和生成器

迭代器和生成器是Python中强大的高级特性,它们允许以高效和优雅的方式处理序列数据。本节将深入探讨迭代器协议、生成器函数和表达式,以及yield语句和协程的使用。通过掌握这些概念,可以编写出更加pythonic和高效的代码。

迭代器协议

迭代器是Python中一个重要的概念,它定义了一种访问集合元素的方式,而不需要了解该集合的底层结构。迭代器协议要求对象实现两个方法:__iter__() 和 __next__()

__iter__() 方法返回迭代器对象本身,而 __next__() 方法返回集合中的下一个元素。当没有更多元素时,__next__() 方法应该引发 StopIteration 异常。

以下是一个简单的迭代器示例:

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

# 使用迭代器
for num in CountDown(5):
    print(num)

这个例子中,CountDown 类实现了迭代器协议。每次调用 __next__() 方法时,它返回当前值并递减计数器。当计数器达到零时,引发 StopIteration 异常,结束迭代。

迭代器的优势在于它们是"惰性"的,只在需要时才计算下一个值,这在处理大型数据集或无限序列时特别有用。

生成器函数和表达式

生成器是创建迭代器的一种更简单的方式。生成器函数使用 yield 语句而不是 return 语句来返回结果。每次调用生成器的 __next__() 方法时,函数会继续执行到下一个 yield 语句。

以下是一个生成器函数的示例:

def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

# 使用生成器函数
for num in fibonacci(10):
    print(num)

这个生成器函数产生斐波那契数列的前n个数。使用 yield 语句,函数在每次迭代时"暂停"并返回当前的斐波那契数,然后在下次调用时从暂停的地方继续执行。

生成器表达式是创建简单生成器的一种简洁方式,类似于列表推导式:

squares = (x**2 for x in range(10))
print(list(squares))  # 将生成器转换为列表并打印

这个生成器表达式创建了一个产生前10个整数平方的生成器。与列表推导式不同,生成器表达式使用圆括号而不是方括号。

yield语句和协程

yield 语句不仅可以用于创建生成器,还可以用于实现协程。协程是一种可以在执行过程中暂停和恢复的函数,这使得它们特别适合于实现状态机、事件处理和异步编程。

以下是一个使用协程的简单示例:

def grep(pattern):
    print(f"Searching for {pattern}")
    while True:
        line = yield
        if pattern in line:
            print(line)

# 使用协程
search = grep("python")
next(search)  # 启动协程
search.send("Hello, world!")
search.send("Python is awesome")
search.send("Programming is fun")
search.close()  # 关闭协程

在这个例子中,grep 函数是一个协程,它持续接收输入行并检查是否包含指定的模式。使用 yield 语句,协程可以暂停执行并等待下一个输入。send() 方法用于向协程发送值,而 next() 或 send(None) 用于启动协程。

协程提供了一种强大的方式来构建数据处理管道和实现并发编程,特别是在处理I/O密集型任务时。

迭代器和生成器是Python中处理序列数据的强大工具。通过实现迭代器协议,可以创建自定义的可迭代对象。生成器函数和表达式提供了一种更简洁的方式来创建迭代器,特别适用于处理大型或无限序列。yield语句不仅用于创建生成器,还可以用于实现协程,为异步编程和复杂的控制流提供了强大的支持。掌握这些概念可以显著提高代码的效率和可读性。

THE END