迭代器与生成器

PythonPythonBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

在本实验中,我们将学习 Python 的内置迭代器(Iterators)、生成器(Generators)和生成器表达式(Generator Expressions)。我们将了解如何使用这些结构来编写高效且优雅的 Python 代码。

学习目标

  • 迭代器(Iterator)
  • 生成器(Generator)
  • 生成器表达式(Generator Expression)

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/ControlFlowGroup(["Control Flow"]) python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/ObjectOrientedProgrammingGroup(["Object-Oriented Programming"]) python(("Python")) -.-> python/ErrorandExceptionHandlingGroup(["Error and Exception Handling"]) python(("Python")) -.-> python/AdvancedTopicsGroup(["Advanced Topics"]) python/ControlFlowGroup -.-> python/for_loops("For Loops") python/ControlFlowGroup -.-> python/list_comprehensions("List Comprehensions") python/FunctionsGroup -.-> python/function_definition("Function Definition") python/ObjectOrientedProgrammingGroup -.-> python/classes_objects("Classes and Objects") python/ErrorandExceptionHandlingGroup -.-> python/raising_exceptions("Raising Exceptions") python/AdvancedTopicsGroup -.-> python/iterators("Iterators") python/AdvancedTopicsGroup -.-> python/generators("Generators") subgraph Lab Skills python/for_loops -.-> lab-84{{"迭代器与生成器"}} python/list_comprehensions -.-> lab-84{{"迭代器与生成器"}} python/function_definition -.-> lab-84{{"迭代器与生成器"}} python/classes_objects -.-> lab-84{{"迭代器与生成器"}} python/raising_exceptions -.-> lab-84{{"迭代器与生成器"}} python/iterators -.-> lab-84{{"迭代器与生成器"}} python/generators -.-> lab-84{{"迭代器与生成器"}} end

迭代器(Iterator)

迭代器是一个可以被迭代(循环)的对象。它会逐个返回数据元素。在 Python 中,迭代器是从可迭代对象(如列表、元组或字符串)创建的。

打开一个新的 Python 解释器。

python3

要在 Python 中创建一个迭代器,我们需要在对象中实现两个方法:__iter____next__

__iter__ 返回迭代器对象本身。__next__ 方法返回迭代器中的下一个值。如果没有更多的元素可以返回,它应该抛出 StopIteration 异常。

以下是一个简单的迭代器示例,它遍历一个数字列表:

class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        ## len() 是列表中元素的数量
        if self.index >= len(self.data):
            raise StopIteration
        result = self.data[self.index]
        self.index += 1
        return result

iterator = MyIterator([1, 2, 3, 4, 5])
for x in iterator:
    print(x)

输出:

1
2
3
4
5

迭代器的有用之处在于它们允许我们逐个访问可迭代对象的元素,而不是一次性将所有元素加载到内存中。这在处理无法完全放入内存的大型数据集时尤其有用。

迭代器还用于在 Python 中实现惰性求值(lazy evaluation)。这意味着迭代器的元素只在需要时生成,而不是一次性生成所有元素。这可能是一种更高效的方法,因为它允许我们避免生成和存储不必要的元素。

如果你想从迭代器中逐个获取元素,可以使用 next() 函数。该函数将返回迭代器中的下一个元素。如果没有更多元素,它将抛出 StopIteration 异常。

iterator = MyIterator([1, 2, 3, 4, 5])
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))

## StopIteration
print(next(iterator))

输出:

1
2
3
4

## StopIteration

以下是 Python 中迭代器的一些常见用例:

  1. 逐个遍历大型数据集的元素。
  2. 实现大型数据集的惰性求值。
  3. 在类中实现自定义的迭代逻辑。
  4. 迭代器是 Python 中的强大工具,可用于编写高效且优雅的代码。

生成器(Generator)

生成器是一种使用函数创建的特殊类型的迭代器。它是一种使用函数创建迭代器的简单方法。

生成器函数的定义与普通函数类似,但它使用 yield 关键字而不是 return 关键字来返回值。当调用生成器函数时,它不会立即执行函数体,而是返回一个生成器对象,该对象可以用于按需执行函数体。

生成器函数可以在其函数体中的任何位置包含 yield 语句。当调用生成器函数时,它不会立即执行函数体,而是返回一个生成器对象,该对象可以用于按需执行函数体。

以下是一个生成器函数的示例,它生成一个数字列表的平方:

def my_generator(data):
    for x in data:
        yield x**2

for x in my_generator([1, 2, 3, 4, 5]):
    print(x)

输出:

1
4
9
16
25

生成器的有用之处在于它们允许我们按需生成元素,而不是一次性生成所有元素。这可能是一种更高效的方法,因为它允许我们避免生成和存储不必要的元素。

生成器还用于在 Python 中实现惰性求值(lazy evaluation)。这意味着生成器的元素只在需要时生成,而不是一次性生成所有元素。这可能是一种更高效的方法,因为它允许我们避免生成和存储不必要的元素。

以下是 Python 中生成器的一些常见用例:

  1. 按需生成元素,而不是一次性生成所有元素。
  2. 实现大型数据集的惰性求值。
  3. 在函数中实现自定义的迭代逻辑。
  4. 生成器是 Python 中的强大工具,可用于编写高效且优雅的代码。

迭代器与生成器的区别

迭代器和生成器的主要区别在于它们的实现方式。

迭代器是一个实现了两个方法的对象:__iter____next____iter__ 方法返回迭代器对象本身,而 __next__ 方法返回迭代器中的下一个值。

生成器是一个使用 yield 关键字返回值的函数。当调用生成器函数时,它不会立即执行函数体,而是返回一个生成器对象,该对象可以用于按需执行函数体。

以下是迭代器和生成器的主要区别总结:

  1. 迭代器是实现 __iter____next__ 方法的对象。它们是从可迭代对象(如列表、元组或字符串)创建的。
  2. 生成器是使用 yield 关键字返回值的函数。它们通过调用生成器函数创建。
  3. 迭代器可以使用类实现,而生成器使用函数实现。
  4. 迭代器逐个返回元素,而生成器返回一个生成器对象,该对象可以用于按需生成元素。
  5. 迭代器用于逐个访问可迭代对象的元素,而生成器用于按需生成元素。

总的来说,迭代器和生成器都是 Python 中用于遍历元素序列的有用工具。它们允许我们逐个访问或生成序列中的元素,这可能比一次性生成所有元素更高效。

高级示例:质数生成器

在这个示例中,我们将创建一个生成质数的生成器。

首先,我们定义一个辅助函数 _is_prime,如果数字是质数则返回 True,否则返回 False

def _is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

现在,我们定义生成器函数 prime_numbers

def prime_numbers(n):
    for i in range(2, n+1):
        if _is_prime(i):
            yield i

让我们测试一下这个生成器:

for prime in prime_numbers(20):
    print(prime)

输出:

2
3
5
7
11
13
17
19

生成器表达式(Generator Expression)

生成器表达式类似于列表推导式(list comprehension),但它返回的是一个生成器对象,而不是列表。

生成器表达式使用圆括号 () 定义,可以包含一个或多个 for 子句。它是按需求值的,并返回一个生成器对象,该对象可以用于按需生成表达式中的元素。

以下是一个生成器表达式的示例,它生成一个数字列表的平方:

generator = (x**2 for x in [1, 2, 3, 4, 5])
for x in generator:
    print(x)

输出:

1
4
9
16
25

生成器表达式的有用之处在于它们允许我们按需生成元素,而不是一次性生成所有元素。这可能是一种更高效的方法,因为它允许我们避免生成和存储不必要的元素。

生成器表达式还用于在 Python 中实现惰性求值(lazy evaluation)。这意味着生成器表达式的元素只在需要时生成,而不是一次性生成所有元素。这可能是一种更高效的方法,因为它允许我们避免生成和存储不必要的元素。

以下是 Python 中生成器表达式的一些常见用例:

  1. 按需生成元素,而不是一次性生成所有元素。
  2. 实现大型数据集的惰性求值。
  3. 编写简洁且高效的代码。

生成器表达式是 Python 中的强大工具,可用于编写高效且优雅的代码。

生成器表达式与列表推导式

以下是一个列表推导式和一个生成器表达式的示例,它们生成一个数字列表的平方:

## 列表推导式
squares = [x**2 for x in [1, 2, 3, 4, 5]]
print(squares)

## 生成器表达式
squares_generator = (x**2 for x in [1, 2, 3, 4, 5])
for x in squares_generator:
    print(x)

输出:

[1, 4, 9, 16, 25]
1
4
9
16
25

列表推导式和生成器表达式之间有几个相似之处和不同之处:

相似之处

  1. 列表推导式和生成器表达式都用于生成一个元素序列。
  2. 两者使用相同的语法,包含一个或多个 for 子句以及一个生成元素的表达式。

不同之处

  1. 列表推导式生成一个列表,而生成器表达式生成一个生成器对象。
  2. 列表推导式一次性生成所有元素,而生成器表达式按需生成元素。
  3. 列表推导式占用更多内存,因为它将所有元素存储在列表中,而生成器表达式占用更少内存,因为它按需生成元素。
  4. 列表推导式通常执行速度更快,因为它一次性生成所有元素,而生成器表达式通常较慢,因为它按需生成元素。

总的来说,列表推导式和生成器表达式都是 Python 中生成元素序列的有用工具。列表推导式通常更快且占用更多内存,而生成器表达式通常较慢且占用更少内存。选择使用哪种方式取决于应用程序的具体需求。

总结

在本实验中,我们学习了 Python 内置的迭代器(Iterators)、生成器(Generators)和生成器表达式(Generator Expressions)。我们了解了如何使用这些结构来编写高效且优雅的 Python 代码。我们还通过一个示例展示了如何使用生成器来实现一个质数生成器。