Python 生成器

Python 生成器

Python 生成器是什么

Python 生成器是返回可迭代对象并用于创建迭代器的功能。它同时遍历所有的项目。生成器也可以是一个表达式,其语法与Python的列表推导类似。

在Python中创建迭代器有很多复杂性;我们需要实现 __iter__()__next__() 方法来跟踪内部状态。

创建迭代器是一个冗长的过程。这就是生成器在简化这个过程中发挥关键作用的原因。如果在迭代中找不到值,它会引发 StopIteration 异常。

如何在Python中创建生成器函数

在Python中,创建生成器并不难。它类似于典型的功能,以def关键字为特征,并使用yield关键字而不是return。或者我们可以说,如果任何功能的主体包含yield语句,它就会自动成为生成器函数。考虑以下示例:

def simple():
for i in range(10):
    if(i%2==0):
         yield i

#Successive Function call using for loop
for i in simple():
    print(i)

输出:

0
2
4
6
8

yield vs. return

yield表达式负责控制生成器函数的执行流程。通过保存所有状态并向调用者进行yield操作,它终止了函数的执行。当调用下一个生成器函数时,它会重新开始执行。在生成器函数中,我们可以使用多个yield语句。

return语句返回一个值并结束整个函数,而且在函数中只能使用一个return语句。

使用多个yield语句

我们可以在生成器函数中使用多个yield语句。考虑以下示例。

def multiple_yield():
    str1 = "First String"
    yield str1

    str2 = "Second string"
    yield str2

    str3 = "Third String"
    yield str3
obj = multiple_yield()
print(next(obj))
print(next(obj))
print(next(obj))

输出:

First String
Second string
Third String

生成器函数和普通函数之间的区别

典型能力只包含一个返回语句,而生成器函数可以包含一个或多个yield语句。

当调用生成器函数时,普通函数立即停止并将控制权交给调用者。

局部变量的状态在调用之间保持不变。

当函数终止时,会自动引发StopIteration异常。

生成器表达式

我们可以在不使用用户定义函数的情况下轻松创建生成器表达式。它类似于lambda函数,可以创建一个匿名函数;生成器表达式通过生成器的表达式创建一个匿名的生成器函数。

生成器表达式的表示方式类似于Python的列表推导式。唯一的区别是圆括号取代了方括号。生成器表达式每次只计算一个元素,而列表推导式会计算整个列表。

考虑以下示例:

list = [1,2,3,4,5,6,7]

# List Comprehension
z = [x**3 for x in list]

# Generator expression
a = (x**3 for x in list)

print(a)
print(z)

输出:

<generator object <genexpr> at 0x01BA3CD8>
[1, 8, 27, 64, 125, 216, 343]

在上面的程序中,列表推导式返回了元素的立方列表,而生成器表达式则返回了计算值的引用。不需要应用for循环,我们也可以在生成器对象上调用next()。让我们考虑另一个示例:

list = [1,2,3,4,5,6]

z = (x**3 for x in list)

print(next(z))

print(next(z))

print(next(z))

print(next(z))

输出:

1
8
27
64

注意:- 当我们调用next()时,Python会在我们将其作为参数传递给的函数上调用next()。

在上述程序中,我们使用了 next() 函数,它返回列表的下一个项目。

示例: 编写一个程序,使用生成器打印给定数字的表。

def table(n):
    for i in range(1,11):
        yield n*i
           i = i+1

for i in table(15):
    print(i)

输出:

15
30
45
60
75
90
105
120
135
150

在上面的示例中,生成器函数正在使用for循环进行迭代。

生成器的优点

生成器有各种优点。以下是其中的一些:

1. 实现简单

与迭代器相比,生成器的实现更简单。在迭代器中,我们需要实现iter()和next()函数。

2. 节省内存

对于许多序列来说,生成器能够高效地利用内存。而生成器函数则计算值并挂起执行,而普通函数会从列表返回一个序列,首先在返回结果之前在内存中创建整个序列。它会在进行逐步调用时继续执行。无限连续的生成器是内存优化的一个很好的示例。让我们在下面的示例中使用sys.getsizeof()函数来进行讨论。

import sys
# List comprehension
nums_squared_list = [i * 2 for i in range(1000)]
print(sys.getsizeof("Memory in Bytes:"nums_squared_list))
# Generator Expression
nums_squared_gc = (i ** 2 for i in range(1000))
print(sys.getsizeof("Memory in Bytes:", nums_squared_gc))

输出:

Memory in Bytes: 4508
Memory in Bytes: 56

我们可以从上面的输出中观察到,列表推导式使用了4508字节的内存,而生成器表达式只使用了56字节的内存。这意味着生成器对象比列表推导式更高效。

3. 使用生成器进行数据管道操作

信息管道可以处理大量数据集或信息流,而不需要额外的计算机内存。

假设我们有一个著名餐馆的日志文件。日志文件有一个部分(第四部分)记录了每天售出的汉堡数量,我们想要统计出四年内售出的汉堡总数。在这种情况下,生成器可以创建一个使用一系列操作的管道。代码如下:

with open('sells.log') as file:
burger_col = (line[3] for line in file)  per_hour = (int(x) for x in burger_col if x != 'N/A')
print("Total burgers sold = ",sum(per_hour))

4. 生成无限序列

生成器可以生成无限的项。无限序列无法存储在内存中,由于生成器每次只生成一个项,可以考虑以下示例:

def infinite_sequence():
    num = 0
    while True:
        yield num
            num += 1

for i in infinite_sequence():
    print(i)

输出:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.........
..........
315
316
317
Traceback (most recent call last):
  File "C:\Users\DEVANSH SHARMA\Desktop\generator.py", line 33, in <module>
    print(i)
KeyboardInterrupt

在本教程中,我们学习了Python生成器。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程