Python 中的生成器

Python 中的生成器

  • Python 中的生成器
    • 生成器表达式
    • 无限流
    • 流水线式生成器

Python 中的生成器

从现在开始,对 Python 的讲解慢慢进入深水区,有什么不理解的,可以在评论区留言询问。

在 Python 中,生成器是一种生成迭代器的方便的方法,可以通过实现生成器函数实现的。生成器函数和普通函数类似,唯一的不同点是,生成器函数使用 yield 语句返回,而不是 return 语句。生成器函数中也可以包含 return 语句,但是 return 语句不是用来返回迭代器的。

根据定义,如果一个函数中至少有一个 yield 语句,那么它就是一个生成函数。使用 yield 语句的主要区别在于,它会暂停函数并保存其内部状态,当下次调用函数时,它会从上次 yield 的行开始。这种设计模式使迭代器功能变得简单而高效。

在内部,__iter____next__ 等方法是自动实现的,StopIteration 异常也是自动引发的。本地属性及其值在连续调用之间被保留,开发者无需执行额外的逻辑。每当 Python 解释器识别到一个生成器函数(包含 yield 语句的函数)时,它就会提供所有这些功能。

为了了解生成器的工作原理,我们将从一个简单的生成器示例开始,该示例用于生成字母表前三个字母的序列:

def 天干迭代器的生成器():
    yield '甲'
    yield '乙'
    yield '丙'
    yield '丁'
    yield '戊'
    yield '己'
    yield '庚'
    yield '辛'
    yield '壬'
    yield '癸'

if __name__ == '__main__':
    iter1 = 天干迭代器的生成器()
    iter2 = 天干迭代器的生成器()
    print(iter1.__next__())
    print(next(iter1))
    print(iter2.__next__())
    print(next(iter2))

在这个例子中,我们使用 yield 语句实现了一个生成器。在主程序中,我们做了以下事情:

  1. 调用 天干迭代器的生成器 函数,获取了两个迭代器,iter1iter2
  2. 对于两个迭代器,调用它的 __next__ 方法,输出一个天干;
  3. 在两个迭代器上调用 next函数,输出下一个天干。

以上代码的输出结果是:

甲
乙
甲
乙

接下来,我们修订 星期类 类,不再单独定义一个迭代器类,而是使用生器生成迭代器。修订后的代码如下:

class 星期类:
    def __init__():.星期字典 = {1: '星期一', 2: '星期二', 3: '星期三', 4: '星期四', 5: '星期五', 6: '星期六', 7: '星期日'}


    def 星期迭代器生成器():
         for key in.星期字典:
             yield.星期字典[key]

if __name__ == '__main__':
    星期 = 星期类()
    iter1 = 星期.星期迭代器生成器()
    iter2 = 星期.星期迭代器生成器()
    print(iter1.__next__())
    print(iter2.__next__())
    print(next(iter1))
    print(next(iter2))

相比之前的代码,这个用生成器生成迭代器的代码,简洁多了。接下来,我们讲解一下生成器的几个关键特性。

生成器表达式

生成器表达式可用于动态创建简单的生成器(也称为匿名函数),而无需编写特殊的方法。语法类似于列表推导式,只是我们使用圆括号而不是方括号。下一个代码示例展示了如何使用生成器表达式创建生成器、它的用法,以及与列表推导式的比较:

L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
#推导式,每个元素加一
f1 = [x + 1 for x in L]
#生成器
g1 = (x + 1 for x in L)

print(f1)

print(g1.__next__())
print(g1.__next__())
print(next(g1))
print(next(g1))

输出结果是:

[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
2
3
4
5

无限流

生成器还可以用来实现数据的无限流。一直以来,把无限流数据放入内存都是一个挑站,这个问题可以用生成器很方便地解决,因为迭代器一次只加载一项数据。下面是一个计算斐波那契数列的例子:

def 斐波那契数列():
    n, a, b = 0, 0, 1
    while True:
        yield a
        a, b = b, a + b
        n += 1

if __name__ == '__main__':
    iter = 斐波那契数列()
    print(next(iter))
    print(next(iter))
    print(next(iter))
    print(next(iter))
    print(next(iter))
    print(next(iter))

流水线式生成器

在处理复杂问题时,可以把多个生成器做成流水线,以实现任何目标。我们可以用一个例子来解释把多个生成器做成流水线的概念。我们要解决的问题是求质数的平方和。这个问题可以通过传统的 for 循环来解决,但我们将尝试使用两个生成器来解决这个问题:质数生成器生成器用于生成质数,平方生成器 生成器用于求出由 质数生成器 生成器送入该生成器的质数的平方。我们将这两个生成器做成流水线输入求和函数,以得到所需的结果。以下是解决问题的代码:

def 是质数(数字):
    for i in range(2, 数字):
        if (数字 % i == 0):
            return False
    return True

def 质数生成器(num):
    for c in range(2, num + 1 ):
        if(是质数(c)):
            yield c

def 平方生成器(质数列表):
    for 质数 in 质数列表:
        yield 质数 * 质数


if __name__ == '__main__':
    iter1 = 平方生成器(质数生成器(5))
    print(next(iter1))
    print(next(iter1))
    print(next(iter1))
    print(sum(平方生成器(质数生成器(5))))

以上代码的输出结果是:

4
9
25
38

生成器是按需运行的,因此不仅内存效率高 还提供了一种在需要时生成值的方法。这有助于避免 不必要的数据生成,因为这些数据可能根本用不上。生成器非常适合 生成器非常适合用于大量数据处理、将数据从一个函数传输到其他函数,以及模拟并行计算。以及模拟并发。

<完>

你可能感兴趣的:(python,开发语言)