什么是惰性求值?(python基础)

本文介绍了惰性求值的概念及应用,通过示例解释了如何利用惰性求值提高程序效率。例如,在布尔运算中,当能确定最终结果时会跳过不必要的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 惰性求值:就是在需要是才进行求值的计算方式,比如  a and b 如果a 为0则不需要去计算b是否为真同理a or b 如果a为1则不需要去计算b是否为真。

<think>我们正在讨论Python中的yield关键字。根据引用内容,yield是用于创建生成器(Generator)的关键字,它允许函数返回一个生成器对象,该对象可以逐个产生值,而不是一次性返回所有值。这种机制称为惰性求值,可以节省内存,特别适合处理大数据或流式数据。关键点总结:1.基本用法:在函数中使用yield语句,该函数就变成了生成器函数。调用生成器函数时,它返回一个生成器对象,而不立即执行函数体。每次调用next()(或使用for循环迭代)时,函数从上次yield的位置继续执行,直到遇到下一个yield。2.生成器可以暂停和恢复:每次执行到yield时,函数暂停并返回yield后面的值;下次从暂停处继续执行。3.高级功能:-使用send()方法可以向生成器发送值(发送的值会成为当前yield表达式的结果)。-使用yieldfrom可以委托给另一个生成器(子生成器),用于简化嵌套生成器的操作。-生成器可以处理异常(通过throw()方法)。4.使用场景:处理大数据集(避免一次性加载所有数据到内存)、流式处理、无限序列、惰性求值等。示例代码(参考引用中的示例):示例1:基础生成器```pythondefsimple_generator():yield1yield2yield3gen=simple_generator()print(next(gen))#输出:1print(next(gen))#输出:2print(next(gen))#输出:3```示例2:使用循环的生成器```pythondefmygenerater(n):foriinrange(n):print('开始生成...')yieldiprint('完成一次...')g=mygenerater(3)print(next(g))#输出:开始生成...然后输出0print(next(g))#输出:完成一次...开始生成...然后输出1print(next(g))#输出:完成一次...开始生成...然后输出2#再调用next(g)会抛出StopIteration异常,因为已经生成完毕```示例3:使用yieldfrom展开嵌套序列(引用2)```pythonfromtypingimportIterabledefflatten(items,ignore_types=(str,bytes)):forxinitems:ifisinstance(x,Iterable)andnotisinstance(x,ignore_types):yieldfromflatten(x)#递归委托给子生成器else:yieldxguys=['lily','alen',['john','tom','jeffery'],['chris','amy']]forxinflatten(guys):print(x,end='\t')#输出:lilyalenjohntomjefferychrisamy```示例4:使用send与生成器交互```pythondefgenerator_with_send():value=yield'First'yieldf'Yousent:{value}'g=generator_with_send()print(next(g))#输出:'First',启动生成器(此时停在第一个yield)print(g.send('Hello'))#发送'Hello',生成器内部value='Hello',然后执行到下一个yield,输出:'Yousent:Hello'```注意事项:-生成器函数第一次调用时,需要使用next()或send(None)来启动(启动后停在第一个yield处)。-当生成器执行完毕(函数执行到return或函数末尾),会抛出StopIteration异常。在for循环中,这个异常会被自动处理。-生成器只能遍历一次,遍历完后就不能再使用了。总结:yield关键字使得函数变为生成器,实现了按需生成值,节省内存。它支持暂停和恢复,并且可以通过send、yieldfrom等实现更复杂的控制流和数据流。§§相关问题§§1.Python生成器与普通函数的区别是什么?2.如何使用yieldfrom简化生成器嵌套?3.生成器在内存管理上有哪些优势?4.如何向生成器发送值(使用send方法)?5.生成器处理异常的方法是什么?</think>### Python `yield`关键字的作用及用法详解 #### 一、核心作用 `yield`是Python生成器(Generator)的核心关键字,主要功能: 1. **惰性求值** 函数执行到`yield`时暂停,返回当前值但不终止函数,下次调用时从中断处继续执行[^5]。 2. **内存高效** 逐个生成值,避免一次性加载所有数据到内存,适合处理大数据流[^1]。 3. **状态保留** 函数内部状态(变量值、执行位置)会被自动保存[^4]。 #### 二、基础用法示例 ```python def simple_generator(): yield 1 yield 2 yield 3 gen = simple_generator() print(next(gen)) # 输出: 1 print(next(gen)) # 输出: 2 print(next(gen)) # 输出: 3 ``` > 每次调用`next()`恢复执行直到遇到下一个`yield`[^4]。 #### 三、高级功能 1. **`yield from`(嵌套生成器)** 展开嵌套序列(如多层列表): ```python from typing import Iterable def flatten(items): for x in items: if isinstance(x, Iterable) and not isinstance(x, str): yield from flatten(x) # 委托给子生成器 else: yield x data = ['a', ['b', ['c', 'd']]] print(list(flatten(data))) # 输出: ['a', 'b', 'c', 'd'] ``` > `yield from`递归处理子序列[^2]。 2. **双向通信(`send()`)** 向生成器发送数据: ```python def interactive_gen(): print("Start") x = yield "Ready" print(f"Received: {x}") yield "Done" g = interactive_gen() print(next(g)) # 输出: "Start" → "Ready" print(g.send(100)) # 输出: "Received: 100" → "Done" ``` > 首次需用`next()`启动,之后用`send(value)`传递值[^1]。 #### 四、典型应用场景 1. **大数据流处理** 逐行读取超大文件: ```python def read_large_file(filename): with open(filename) as f: while line := f.readline(): yield line.strip() # 使用示例(内存占用恒定) for line in read_large_file("huge_data.txt"): process(line) # 逐行处理 ``` 2. **无限序列生成** 斐波那契数列生成器: ```python def fibonacci(): a, b = 0, 1 while True: yield a a, b = b, a + b fib = fibonacci() print(next(fib)) # 0 print(next(fib)) # 1 print(next(fib)) # 1 ``` 3. **状态机实现** 简化复杂状态流转: ```python def traffic_light(): states = ["RED", "GREEN", "YELLOW"] index = 0 while True: yield states[index] index = (index + 1) % len(states) light = traffic_light() print(next(light)) # RED print(next(light)) # GREEN ``` #### 五、注意事项 1. 生成器**只能迭代一次**,耗尽后需重新创建[^5]。 2. 使用`try...finally`确保资源释放: ```python def safe_generator(): try: yield "Resource opened" # ...操作资源 finally: print("释放资源") # 即使生成器提前关闭也会执行 ``` #### 六、与普通函数对比 | 特性 | 普通函数 | 生成器函数 | |--------------|------------------|-------------------| | 返回值 | `return`单次返回 | `yield`多次返回值 | | 内存占用 | 一次性加载结果 | 按需生成 | | 执行状态 | 每次调用重置 | 保留暂停状态 | | 适用场景 | 确定结果集 | 流式数据/大集合 | > 生成器本质是实现了迭代器协议(`__iter__`和`__next__`)的语法糖[^5]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值