Python - 生成器

Python - 生成器 首页 / Python3入门教程 / Python - 生成器

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

在Python中创建迭代有很多复杂性。无涯教程需要实现 __ iter __() __ next __()方法来跟踪内部状态。

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

创建函数

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

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

#使用 for 循环的连续函数调用
for i in simple():
    print(i)

输出:

0
2
4
6
8

yield与return

yield 语句负责控制生成器函数的流程。它通过保存所有状态并让出给调用者来暂停函数执行。稍后,当调用后续函数时,它将恢复执行。可以在生成器函数中使用多产量声明。

return语句返回,并终止整个函数,并且该函数中只能使用一个return语句。可以在生成器函数中使用多个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

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

  • 普通函数仅包含一个 return 语句,而生成器函数可以包含一个或多个 yield 语句。
  • 调用生成器函数时,普通函数会立即暂停,并将控制权转移给调用者。
  • 在连续调用之间会记住局部变量及其状态。
  • 该函数终止时,会自动引发StopIteration异常。

生成器表达式

可以轻松创建生成器表达式,而无需使用用户定义的函数。它与创建匿名函数的lambda函数相同;生成器的表达式创建一个匿名生成器函数。

唯一的区别是方括号被圆括号替换。列表推导计算整个列表,而生成器表达式一次计算一次。

考虑以下示例:

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

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

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))
# 生成器表达式
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.用生成器流水线  -  数据管道提供了无需使用额外的计算机内存即可处理大型数据集或数据流的函数

假设有一家著名餐厅的日志文件。日志文件中有一列(第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 <module>
    print(i)
KeyboardInterrupt

祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)

技术教程推荐

赵成的运维体系管理课 -〔赵成〕

持续交付36讲 -〔王潇俊〕

Go语言核心36讲 -〔郝林〕

技术管理实战36讲 -〔刘建国〕

设计模式之美 -〔王争〕

Electron开发实战 -〔邓耀龙〕

技术管理案例课 -〔许健〕

Python自动化办公实战课 -〔尹会生〕

手把手带你写一个 MiniTomcat -〔郭屹〕

好记忆不如烂笔头。留下您的足迹吧 :)