欢迎访问宙启技术站
智能推送

从头开始学习Python生成器函数

发布时间:2023-06-23 11:44:43

Python是一种高级编程语言,因其简单易学、对初学者友好和功能强大而备受欢迎。Python语言的独特之处在于其支持诸如生成器等高级特征。生成器是函数,但是它们没有返回值,而是通过yield语句生成数据。这个提供了许多惊人的机会,因此在本文中,我们将一步一步地学习Python生成器函数。

什么是Python生成器函数?

生成器函数是以def关键字定义的函数。不同于其他函数及任何普通的函数,Python生成器函数使用yield语句返回值。在Python生成器函数中,yield语句包括return,不同的是yield语句可以返回值并暂停函数执行。当暂停执行时,生成器函数的状态被冻结,以便稍后可以恢复状态并从上次离开的地方继续执行。

生成器使用迭代协议实现。这允许生成器在生成值时将计算延迟到请求值时。生成器函数不会将所有计算完成。相反,它将计算延迟到需要值时进行。

生成器函数的语法:

以下是Python生成器函数的语法:

def generator_function(parameters):
  statements
  yield value

在此语法中,generator_function是生成器函数的名称,parameters是要传递到函数中的参数,statements是要执行的操作,而yield value是从函数返回的值。

生成器与函数之间的区别

Python生成器函数与其他函数相比有以下区别:

- 函数使用return语句返回值。生成器使用yeild语句返回值。

- 函数一次性生成所有结果。生成器在请求值时按需生成结果。

- 函数只能从头开始调用。生成器可以从上一次调用继续执行。

生成器使用

生成器可以用于各种目的。以下是一些用于生成器的示例:

- 在需要使用很大的数组时,生成器可以减少内存的使用量。

- 在需要处理需要循环遍历的的序列时,使用生成器可以优化代码和提高性能。

- 在需要生成一个无限流的值时,生成器很有用。无限流是指可以一直生成值的流,而不是将所有值一次性生成。

生成器示例

以下是一个简单的生成器函数示例,它计算所有整数的平方值:

def squares(n):
    for i in range(n):
        yield i**2
        
s = squares(5)
for x in s:
    print(x)

运行以上代码会输出以下结果:

0
1
4
9
16

在此示例中,squares()函数返回一个生成器对象。该生成器函数生成一个用于生成n个整数求平方的迭代器。当迭代器的下一项请求时,生成器返回一个值。for循环使用生成器一次生成一个部分并打印每个值。

支持链式调用的Python生成器函数

Python生成器函数支持链式调用。链式调用是Python的一种编程模式,它允许使用生成器函数的返回值作为输入传递到其他生成器函数中。

以下是例如懒加载器中使用的链式调用:

def squares(n):
    for i in range(n):
        yield i**2

def double(n):
    for i in n:
        yield i*2

s = squares(5)
d = double(s)
for x in d:
    print(x)

运行以上代码会输出以下结果:

0
2
8
18
32

在此示例中,我们首先通过squares()生成器生成一个单独迭代器s。然后我们将此生成器传递给了另一个名为double()的生成器。在double()中,我们将每个值都乘以2并返回它。最后,我们使用for循环查看每个值。

使用next()函数和Python生成器

使用next()函数可以请求Python生成器的下一个值。在此示例中,我们将使用上述示例中使用的同一squares()和double()函数,并编写一个示例以使用Python next()函数请求值。

def squares(n):
    for i in range(n):
        yield i**2

def double(n):
    for i in n:
        yield i*2

s = squares(5)
d = double(s)

print(next(d))
print(next(d))

运行以上代码会输出以下结果:

0
2

在此示例中,我们首先将squares()调用封装到迭代器中并将其传递给double()函数。接下来,我们使用next()函数两次请求double()函数的下两个值。

迭代器和Python生成器

在上面的示例中,我们已经看到Python生成器是一种迭代器。它们使用迭代协议来实现,这使得它们可以按需生成值。然而,有些Python继承的迭代器是迭代器,但不一定是生成器。这是因为它们可能没有使用yield语句来产生值。

下面是一个简单的示例,其中我们实现一个经典的迭代器。请注意,它不使用生成器或yield语句。

class Reverse:
    def __init__(self, data):
        self.data = data
        self.index = len(data)
    def __iter__(self):
        return self
    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index -= 1
        return self.data[self.index]

rev = Reverse('hello')
for char in rev:
    print(char)

运行以上代码会输出以下结果:

o
l
l
e
h

在此示例中,我们使用类创建了Reverse对象。Reverse对象是一个经典的Python迭代器。使用__iter__方法返回一个迭代器对象,并使用__next__方法获取下一个值。当我们到达字符串的末尾时,我们使用StopIteration异常停止迭代。最后,我们使用for循环遍历迭代器。

结论

Python生成器是一种高级特性,可用于多种目的,包括减少内存使用、优化代码并生成无限流。Python生成器函数使用yield语句代替return语句来返回值,并可以使用迭代协议实现。生成器函数可以和其他函数链式调用,也可以使用next()函数请求下一个值。如果在Python中需要自己构建迭代器,也可以使用经典的迭代器来进行构建。