📜  Python生成器

📅  最后修改于: 2020-10-28 01:28:05             🧑  作者: Mango

Python生成器

什么是Python生成器?

Python生成器是返回遍历对象并用于创建迭代器的函数。它一次遍历整个项目。生成器也可以是一个表达式,其语法类似于Python的列表理解。

用Python创建迭代有很多复杂性;我们需要实现__iter __()和__next __()方法来跟踪内部状态。

创建迭代器是一个漫长的过程。因此,生成器在简化此过程中起着至关重要的作用。如果在迭代中找不到任何值,则会引发StopIteration异常。

如何在Python创建Generator函数?

在Python创建生成器非常简单。它类似于def关键字定义的常规函数,并使用yield关键字而不是return。或者我们可以说,如果任何函数的主体包含yield语句,它将自动成为generator函数。考虑以下示例:

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语句负责控制生成器函数的流程。它通过保存所有状态并让出给调用者来暂停函数执行。稍后,当调用后续函数时,它将恢复执行。我们可以在generator函数使用Multiple yield语句。

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

使用多重收益声明

我们可以在generator函数使用Multiple 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

生成器函数与常规函数之间的区别

  • 普通函数仅包含一个L return语句,而生成器函数可以包含一个或多个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)

输出:

 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()函数,该函数返回了列表的下一项。

示例:编写程序以使用生成器print给定编号的表。

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.Pipelining with Generators

数据管道提供了无需使用额外的计算机内存即可处理大型数据集或数据流的功能。

假设我们有一家著名餐厅的日志文件。日志文件中有一个列(第4列),该列跟踪每小时出售的汉堡的数量,我们希望对其进行汇总以得出4年内出售的汉堡的总数。在这种情况下,生成器可以生成具有一系列操作的管道。下面是它的代码:

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 
    print(i)
KeyboardInterrupt

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