当前位置: 首页 > news >正文

科普:Python 中, `return`与`yield` (及<generator object fibonacci at 0x.........>)

看如下程序:

# 定义一个生成斐波那契数列的生成器函数
def fibonacci():a, b = 0, 1while True: # 1、死循环?yield aa, b = b, a + b# 调用生成器函数 → 得到生成器对象(而非直接返回数列值)
gen = fibonacci()
print(gen)  # 2、输出是什么?

程序中我打了两个问号:1、死循环?2、输出是什么?
对于第2个问号(2、输出是什么?),一运行便知:<generator object fibonacci at 0x0000017FF0903850>(地址可能不同)。即:这里直接打印 gen 就会显示生成器对象的信息,而不是斐波那契数列的具体值——这是生成器“惰性计算”的特性决定的(不会提前生成数据,而是生成生成器的对象,然后由生成器的对象按需生成数据)。

为回答第一个问号(),我们比较returnyield两关键字。
在 Python 中,y ieldreturn 都是用于在函数中返回值的关键字,但它们的行为和适用场景有本质区别,核心差异在于是否终止函数执行以及返回值的方式

1. 基本功能与函数类型

  • return:用于普通函数,作用是返回一个值并立即终止函数,函数的局部状态(如变量、执行位置)会被销毁。
  • yield:用于生成器函数(包含 yield 的函数),作用是返回一个值并暂停函数执行,同时保存函数当前的状态(局部变量、执行位置等),下次调用时从暂停处继续执行。

2. 执行流程对比

(1)return 的执行流程
def return_func():print("步骤1")return 1  # 返回值并终止函数print("步骤2")  # 永远不会执行result = return_func()
print(result)  # 输出:步骤1 → 1
  • 函数执行到 return 时,立即返回值并结束,后续代码不再执行。
  • 再次调用函数时,会重新从头开始执行。
(2)yield 的执行流程
def yield_func():print("步骤1")yield 1  # 返回值并暂停print("步骤2")yield 2  # 返回值并暂停print("步骤3")# 调用生成器函数,返回生成器对象(不执行函数体)
gen = yield_func()# 第一次触发:执行到第一个yield,返回1并暂停
print(next(gen))  # 输出:步骤1 → 1# 第二次触发:从暂停处继续,执行到第二个yield,返回2并暂停
print(next(gen))  # 输出:步骤2 → 2# 第三次触发:从暂停处继续,执行完剩余代码,无更多yield,抛出StopIteration
print(next(gen))  # 输出:步骤3 → 报错(StopIteration)
  • 生成器函数被调用时,不会立即执行,而是返回一个生成器对象。
  • 每次通过 next(生成器) 或迭代触发时,函数执行到下一个 yield 处暂停,返回值并保存状态。
  • 直到函数执行完毕(无更多 yield),再次调用会抛出 StopIteration 异常。

3. 返回结果的差异

  • return:直接返回一个具体的值(或 None),调用函数后立即得到结果。

    def add(a, b):return a + bprint(add(2, 3))  # 直接得到结果:5
    
  • yield:返回的是一个生成器对象(一种特殊的迭代器),而非直接返回值。需要通过迭代(如 for 循环)或 next() 方法逐步获取值。

    def generate_numbers(n):for i in range(n):yield i# 生成器对象本身不是结果,需要迭代获取
    gen = generate_numbers(3)
    print(next(gen))  # 0
    print(next(gen))  # 1
    

4. 内存与适用场景

  • return:适合返回有限且少量的数据,因为它会一次性将所有结果加载到内存中(例如返回一个列表)。

    def get_list(n):return [i for i in range(n)]  # 一次性生成所有数据,占用内存print(get_list(5))  # [0, 1, 2, 3, 4]
    
  • yield:适合返回大量数据、无限序列,或需要按需生成数据的场景(节省内存)。因为它不会一次性生成所有数据,而是“按需产出”。

    def infinite_numbers():i = 0while True:yield i  # 无限生成数据,不占用大量内存i += 1# 取前5个值,无需生成所有数据
    gen = infinite_numbers()
    for _ in range(5):print(next(gen), end=" ")  # 0 1 2 3 4
    

这样功能就回答了文章开头提出的第一个问题(1、死循环?):它并是不去执行死循环,而是根据需要执行“有限”步骤。

5. 其他关键区别

  • 在生成器中使用 return:生成器函数中也可以用 return,但它不会返回值(会被忽略),而是直接触发 StopIteration 异常,终止生成器。

    def gen_with_return():yield 1return  # 触发StopIterationyield 2  # 不会执行gen = gen_with_return()
    print(next(gen))  # 1
    print(next(gen))  # 报错:StopIteration
    
  • yield 不能在普通函数中使用:如果普通函数(无 yield)中使用 yield,会报错;反之,生成器函数中可以没有 return(默认执行到末尾触发 StopIteration)。

特性returnyield
函数类型普通函数生成器函数
执行效果返回值并终止函数返回值并暂停函数(保存状态)
返回结果直接返回具体值返回生成器对象(需迭代取值)
内存占用一次性加载所有结果,占用内存较多按需生成,内存占用低
适用场景返回有限/少量数据,立即获取结果大量数据、无限序列、按需生成

简单说:return 是“一去不返”(终止函数),yield 是“藕断丝连”(暂停并可恢复)。

http://www.dtcms.com/a/475347.html

相关文章:

  • 站群服务器是什么意思源码下载网站推荐
  • 广东住房和城乡建设厅网站做网站建设优化的公司
  • shell创建tar gz文件
  • 企业二级域名自助建站平台北京商地网站建设公司
  • Linux性能分析实战指南
  • 营销型企业网站源码wordpress anki插件
  • “Fontconfig head is null”错误的终极排查与修复
  • 纯 flash 网站有没有免费的虚拟主机
  • ARP介绍
  • 网站维护费大概多少国际贸易网站大全
  • wordpress 三站合一大专电子商务主要学什么
  • 网站开发语言学习免费做qq互赞网站
  • 什么平台可以做网站北京西站地址
  • 做地方网站能赚钱吗昆明找工作哪个网站好
  • 【复习】计网每日一题1004--传输效率
  • 西安市环评建设备案网站室内设计招聘网站有哪些
  • 呼市地区做网站公司美丽女性网-大型女性门户网大型程序700m网站程序源码织梦
  • 基于AHP-熵权法-TOPSIS的学习能力评价研究
  • FDBus(Fast Distributed Bus)
  • 淘宝客网站如何做排名北京朝阳区地图高清版大图
  • 公司建设网站的服务费汉中住房和城乡建设部网站
  • 吴川网站开发公司网站空间位置是什么
  • 如何查询网站是否有做404淄博网站建设 华夏国际
  • 养老院网站建设做图的模板下载网站
  • 杭州比较好的代运营公司电子商务seo实训总结
  • java锁升级简述
  • 网站含中国的备案外贸网站建设公司青岛
  • 图片 网站源码免费企业查询
  • 中国逐日格点降水数据集V2(1960–2024,0.1°)
  • 公司的网址杭州百家号优化