生成器

概念

Python生成器是一种特殊的函数,它可以在需要时生成一个序列的值。与普通函数不同,生成器函数使用yield语句或生成器表达式(也叫生成器推导式)来产生值,并且可以暂停和恢复执行。生成器可以逐个生成值,而不是一次性生成整个序列,这样可以节省内存并提高性能。

一般与循环语句(for、while)、next函数等结合使用

生成器在处理大量数据或无限序列时非常有用,可以节省内存和提高性能。

它们还可以用于创建可迭代的对象,并且可以通过for循环来遍历。

生成器表达式可以简化代码,特别是在需要生成复杂序列时。

生成器可以通过两种方式创建:生成器函数和生成器表达式。

生成器函数(yield关键字的应用)

生成器函数是一种使用yield语句的函数即函数中出现了yield关键字,就表示此函数是生成器函数。

当函数被调用时,它返回一个生成器对象,可以使用next()函数来逐个获取生成器中的值

每次执行到yield语句时,函数会暂停执行并返回一个值给调用方

当再次调用next()函数时,函数会从上次离开的地方继续执行,直到遇到下一个yield语句。

复制代码
def my_generator():
    yield 1
    yield 2
    yield 3


gen = my_generator()
print(type(gen))  # <class 'generator'>
print(next(gen))  # 输出: 1
print(next(gen))  # 输出: 2
print(next(gen))  # 输出: 3
复制代码

 

生成器表达式也叫生成器推导式

生成器表达式是一种类似于列表推导式的语法,但使用圆括号而不是方括号。

它们可以在创建生成器时非常方便,因为它们不需要一次性生成整个序列。生成器表达式可以通过迭代来访问生成器中的值。

复制代码
 1 '''
 2 生成器表达式也叫生成器推导式。是一种类似于列表推导式的语法,但使用圆括号而不是方括号。
 3 它们在创建生成器时非常方便,因为它们不需要一次性生成整个序列。生成器表达式可以通过迭代来访问生成器中的值。
 4 
 5 
 6 '''
 7 
 8 # 1. 定义生成器
 9 gen = (x for x in range(1, 4))
10 print(type(gen))  # <class 'generator'>
11 # 2. 一般与循环、next函数等结合使用
12 print(next(gen))  # 输出: 1
13 print(next(gen))  # 输出: 2
14 print(next(gen))  # 输出: 3
复制代码

生成器的特点

  1. 惰性机制
  2. 只能向前
  3. 节省内存

在代码中的体现:

  1. 生成器代码执行到yield会返回结果,下次启动生成器会从暂停位置继续向下执行

  2. 生成器把数据全部生成完成,再向下执行会抛出StopIteration异常

  3. while循环需要手动处理异常

  4. for循环内部自动回处理异常

复制代码
 1 def my_generator():
 2     yield 1
 3     yield 2
 4     yield 3
 5 
 6 
 7 gen = my_generator()
 8 '''
 9 输出:
10     Traceback (most recent call last):
11       File "D:\allen_class\python\base\base\043生成器\03异常.py", line 10, in <module>
12         print(next(gen))
13               ^^^^^^^^^
14     StopIteration
15     1
16     2
17     3
18 '''
19 while True:
20     print(next(gen))  # 会抛异常
复制代码
复制代码
 1 def my_generator():
 2     yield 1
 3     yield 2
 4     yield 3
 5 
 6 gen = my_generator()
 7 
 8 try:
 9     while True:
10         value = next(gen)
11         print(value)
12 except StopIteration:
13     pass
14 
15 # Output: 1 2 3
复制代码

 

复制代码
 1 '''
 2 for循环不会触发StopIteration异常
 3 '''
 4 
 5 
 6 def my_generator():
 7     yield 1
 8     yield 2
 9     yield 3
10 
11 
12 '''
13 输出:
14     1
15     2
16     3
17 '''
18 gen = my_generator()
19 for i in gen:
20     print(i)
复制代码

 

 

生成器的最佳实践

  • 使用生成器来处理大量数据或无限序列,以避免一次性加载整个序列到内存中;
  • 使用生成器函数和yield语句来编写可迭代的对象,并且可以通过for循环来遍历它们;
  • 使用生成器表达式来简化代码,特别是在需要生成较复杂的序列时。

 

典型示例:斐波那契数列 

什么是斐波那契数列(Fibonacci sequence)?

又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称“兔子数列”。

其数值为:1、1、2、3、5、8、13、21、34……在数学上,这一数列以如下递推的方法定义:

F(0)=1,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)。这个数列从第三项开始,每一项都等于前两项之和

示例

复制代码
 1 # 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
 2 def fb(num):
 3     a = 0
 4     b = 1
 5 
 6     # 记录生成了几个数字
 7     index = 0
 8 
 9     while index < num:
10         print(f"index={index}")
11         result = a
12         a, b = b, a + b
13         print(f"index={index},result={result}")
14         yield result
15         index += 1
16 
17 
18 gen = fb(5)
19 # 以下语句,可以验证生成器只能往下走,不能回头
20 # print(next(gen))  # 0
21 # print(next(gen))  # 1
22 for i in gen:
23     print(i)
复制代码

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
index=0
index=0,result=0
0
index=1
index=1,result=1
1
index=2
index=2,result=1
1
index=3
index=3,result=2
2
index=4
index=4,result=3
3

  

 

posted @   Allen_Hao  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示