Python 高级特性(4)- 生成器 generator

简介: Python 高级特性(4)- 生成器 generator

列表生成式


通过上一篇介绍 列表生成式文章可以知道,它可以快速创建我们需要的列表

 

局限性

  • 受内存限制,列表生成式创建的列表的容量肯定有限的
  • 不仅占用很大的存储空间,如果我们仅仅需要访问前几个元素,那后面绝大多数元素占用的空间都白白浪费了

 

什么是生成器


  • 若列表元素可以按照某种算法算出来,就可以在循环的过程中不断推算出后续需要用的元素,而不必创建完整的 list,从而节省大量的空间
  • 边循环边计算的机制,叫生成器(generator)

 

最简单的生成器


L = [x * x for x in range(10)]
print(L)
print(type(L))
L = (x * x for x in range(10))
print(L)
print(type(L))
# 输出结果
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
<class 'list'>
<generator object <genexpr> at 0x000001D607541EB8>
<class 'generator'>


只要把一个列表生成式的 [] 改成 () ,就创建了一个 generator

 

如何打印生成器每个元素


直接简单 for 循环

L2 = (x * x for x in range(10))
for i in L2:
    print(i)


next() 方法

可以获取 generator 的下一个元素

基本不会使用这个

L2 = (x for x in range(10))
print(next(L2))
print(next(L2))
print(next(L2))
print(next(L2))
print(next(L2))
print(next(L2))
# 输出结果
0
1
2
3
4
5


还有另一个方法 .__next()__

L2 = (x for x in range(10))
print(L2.__next__())
print(L2.__next__())
print(L2.__next__())
print(L2.__next__())
print(L2.__next__())
print(L2.__next__())
# 输出结果
0
1
2
3
4
5


生成器的迭代原理


generator 能够迭代的关键就是 next() 方法,通过重复调用 next() 方法,直到捕获一个异常

 

yield 函数


  • 带有 yield的函数不再是一个普通函数,而是一个生成器 generator
  • yield 相当于 return 返回一个值,并且记住这个返回值的位置,下次迭代时,代码会从 yield 的下一条语句开始执行,直到函数结束或遇到下一个 yield

 

普通的斐波拉契数列


1, 1, 2, 3, 5, 8, 13, 21, 34, ...,除第一个和第二个数外,任意一个数都可由前两个数相加得到

# 斐波拉契数列
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
fib(8)
# 输出结果
1
1
2
3
5
8
13
21


它和生成器很像,知道第一个元素值,就可以推算后面的任意个元素了

 

是用 yield 的斐波拉契数列


def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
fib(8)
print(fib(8))
# 输出结果
1
1
2
3
5
8
13
21
<generator object fib at 0x00000246A5001EB8>


生成器的执行流程


函数是顺序执行,遇到 return 或者最后一行执行完就返回

 

而生成器的执行流程是

  • 每次调用 next() 或 for 循环的时候执行,遇到 yield 就返回
  • 一个生成器里面可以有多个 yield
  • 再次执行时从上次返回的 yield 语句处继续执行


# 执行流程
def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield 3
    print('step 3')
    yield 5
L = odd()
for i in L:
    print(i)
# 输出结果
step 1
1
step 2
3
step 3
5


生成器的工作原理


  • 它是在 for 循环过程中不断计算下一个元素,并在适当的条件结束 for 循环
  • 对于函数改成的 generator 来说,,遇到 return 语句或者执行到函数最后一行时,就是结束 generator 的指令,for 循环随之结束

 

生成器的优点


在不牺牲过多速度情况下,释放了内存,支持大数据量的操作

 

不使用生成器下的代码

from tqdm import tqdm
a = []
for i in tqdm(range(10000000)):
    temp = ['你好'] * 2000
    a.append(temp)
for ele in a:
    continue


image.png


可以看到开始运行大数据量循环代码后,内存暴增,并且占满了电脑所有内存,很明显这是不合理且不可接受的!

 

使用生成器的代码

def test():
    for i in tqdm(range(10000000)):
        temp = ['你好'] * 2000
        yield temp
a = test()
for ele in a:
    continue


image.png


内存丝滑的很,奈斯!

 

生成器的应用场景

当然就是需要处理大数据量的场景了,比如一个文件有几百万行数据,或者有几百万个文件需要分别读取处理

 

相关文章
|
2月前
|
算法 大数据 Python
Python生成器:优雅而高效的迭代器
Python生成器:优雅而高效的迭代器
|
1天前
|
Python
【Python操作基础】——字典,迭代器和生成器
【Python操作基础】——字典,迭代器和生成器
|
4天前
|
存储 程序员 Python
深入理解Python中的生成器和迭代器
本文将深入探讨Python中生成器和迭代器的概念、原理以及它们在编程中的应用。通过详细解析生成器和迭代器的工作机制,读者将能够更好地理解Python中的迭代器协议、生成器函数以及生成器表达式的使用方法。同时,本文还将介绍生成器和迭代器在Python中的一些常见应用场景,并提供一些实用的编程技巧和最佳实践。
|
13天前
|
大数据 Python
python中的推导式、生成器(二)
python中的推导式、生成器(二)
|
13天前
|
索引 Python 容器
python中的推导式、生成器(一)
python中的推导式、生成器(一)
|
16天前
|
存储 Python
深入理解Python中的生成器和迭代器
本文将深入探讨Python中生成器和迭代器的概念及其在实际编程中的应用。通过对生成器和迭代器的原理解析,以及实际案例的演示,读者将能够更好地理解和利用这些强大的编程工具。
|
18天前
|
运维 Shell Sentinel
第八章 Python可迭代对象、迭代器和生成器
第八章 Python可迭代对象、迭代器和生成器
|
19天前
|
数据采集 存储 大数据
Python中的迭代器与生成器
Python中的迭代器与生成器
15 0
|
25天前
|
存储 并行计算 计算机视觉
SciPy高级特性:稀疏矩阵与并行计算
【4月更文挑战第17天】SciPy是科学计算库,包含稀疏矩阵处理和并行计算等高级特性。稀疏矩阵适用于处理大量零元素的情况,如网络分析和图像处理,SciPy提供CSC、CSR、COO和LIL等多种存储格式。并行计算通过`joblib`和`multiprocessing`模块实现,能加速大规模计算任务。结合两者可高效解决大规模线性方程组等问题。
|
25天前
|
大数据 Python
Python中的`yield`:掌握生成器的精髓
【4月更文挑战第17天】`yield`在Python中用于创建生成器,一种节约内存的迭代器。生成器函数在迭代时暂停并保存状态,下次迭代时继续执行,适用于处理大数据、实现协程和优化内存。`yield`不同于普通函数,不立即计算所有结果,而是在需要时生成单个值。使用场景包括生成大列表、实现协程和简化迭代逻辑。注意`yield`后的值不能是表达式,生成器只能调用一次,且`yield`与`return`作用不同。理解并善用`yield`能提升Python编程效率。