Python 生成器

在 Python 中,生成器是一个函数,它返回一个迭代器,该迭代器在被迭代时会产生一个值序列。

当我们想要生成一个庞大的值序列,但又不想一次性将它们全部存储在内存中时,生成器就非常有用。


创建 Python 生成器

在 Python 中,与定义普通函数类似,我们可以使用 def 关键字来定义一个生成器函数,但我们使用 yield 语句而不是 return 语句。

def generator_name(arg):
    # statements
    yield something

这里,yield 关键字用于从生成器中产生一个值。

当生成器函数被调用时,它不会立即执行函数体。相反,它会返回一个生成器对象,可以通过迭代该对象来产生值。


示例:Python 生成器

这是一个生成器函数的示例,它会产生一个数字序列,

def my_generator(n):

    # initialize counter
    value = 0

    # loop until counter is less than n
    while value < n:

        # produce the current value of the counter
        yield value

        # increment the counter
        value += 1

# iterate over the generator object produced by my_generator
for value in my_generator(3):

    # print each value produced by generator
    print(value)

输出

0
1
2

在上面的示例中,my_generator() 生成器函数接受一个整数 n 作为参数,并使用 while 循环产生一个从 0n-1 的数字序列。

yield 关键字用于从生成器中产生一个值,并暂停生成器函数的执行,直到请求下一个值为止。

for 循环遍历由 my_generator() 产生的生成器对象,而 print 语句则打印出生成器产生的每个值。

我们也可以像调用任何其他函数一样,通过调用生成器函数来创建一个生成器对象,如下所示:

generator = my_range(3)
print(next(generator))  # 0
print(next(generator))  # 1
print(next(generator))  # 2

注意:要了解更多信息,请访问 range()for 循环()


Python 生成器表达式

在 Python 中,生成器表达式是创建生成器对象的一种简洁方式。

它类似于列表推导式,但它创建的是一个生成器对象,而不是列表。这个生成器对象可以被迭代以产生生成器中的值。

生成器表达式语法

生成器表达式具有以下语法:

(expression for item in iterable)

这里,expression 是将为 iterable 中的每个项返回的值。

生成器表达式创建了一个生成器对象,该对象在被迭代时,会为 iterable 中的每个项一次一个地产生 expression 的值。


示例 2:Python 生成器表达式

# create the generator object
squares_generator = (i * i for i in range(5))

# iterate over the generator and print the values
for i in squares_generator:
    print(i)

输出

0
1
4
9
16

在这里,我们创建了一个生成器对象,当被迭代时,它将产生数字 04 的平方。

然后,为了迭代生成器并获取值,我们使用了 for 循环。


Python 生成器的用途

有几个原因使得生成器成为一种强大的实现方式。

1. 易于实现

与它们的迭代器类对应物相比,生成器可以以一种清晰简洁的方式实现。以下是使用迭代器类实现 2 的幂序列的示例。

class PowTwo:
    def __init__(self, max=0):
        self.n = 0
        self.max = max

    def __iter__(self):
        return self

    def __next__(self):
        if self.n > self.max:
            raise StopIteration

        result = 2 ** self.n
        self.n += 1
        return result

上面的程序冗长且令人困惑。现在,让我们使用生成器函数来做同样的事情。

def PowTwoGen(max=0):
    n = 0
    while n < max:
        yield 2 ** n
        n += 1

由于生成器会自动跟踪细节,因此实现更加简洁和清晰。

2. 内存效率高

一个返回序列的普通函数会在返回结果之前在内存中创建整个序列。如果序列中的项目数量非常大,这是一种过度消耗。

这种序列的生成器实现对内存友好,是首选方式,因为它一次只产生一个项目。

3. 表示无限流

生成器是表示无限数据流的绝佳媒介。无限流无法存储在内存中,而由于生成器一次只产生一个项目,它们可以表示无限的数据流。

下面的生成器函数可以生成所有偶数(至少在理论上是这样)。

def all_even():
    n = 0
    while True:
        yield n
        n += 2

4. 管道化生成器

多个生成器可以用于将一系列操作管道化。用一个例子可以最好地说明这一点。

假设我们有一个生成器,它产生斐波那契数列中的数字。我们还有另一个用于求数字平方的生成器。

如果我们想找出斐波那契数列中数字的平方和,我们可以通过将生成器函数的输出管道化输出来实现,如下所示。

def fibonacci_numbers(nums):
    x, y = 0, 1
    for _ in range(nums):
        x, y = y, x+y
        yield x

def square(nums):
    for num in nums:
        yield num**2

print(sum(square(fibonacci_numbers(10))))

# Output: 4895

这种管道化方式高效且易于阅读(而且,是的,酷多了!)。

视频:Python 生成器

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战