深入探秘Python生成器:揭开神秘的面纱
一、问题起源:
想象一下,您掌握了一种魔法,在代码世界里,您可以轻松呼唤出一个整数。然而,事情并不总是看起来那样简单。在Python的奇妙王国中,我遇到了一个有趣的谜题:
def tst():try:print('hello world')return 1except:yield 2
print(tst())
type(tst())
表面上,这段代码看起来像是在进行一个简单的问候和返回神秘数字1的仪式。但是,执行后,却揭晓了一个出乎意料的结果:
<generator object tst at 0x00000255F7E039F0>
generator
这个不是预期中的整数!而是一种被称为生成器的强大生物。那么,这是如何发生的呢?
二、魔法解密:为何它是生成器?
一段代码的命运,在Python领域里,是由它出生(定义)的时刻就注定了。就像预言中说的,函数的行为被它的定义方式固定下来,而非仅仅由它实际运行时的动作决定。
Python中的先知们(编译器),在瞥见函数的定义时,会使用他们的预言之眼(分析功能),寻找隐藏于代码深处的yield这个关键词符。发现了yield,哪怕它藏在一条不曾通往的冷僻小径上(逻辑上不可达的代码块),编译器也会宣告:这是一个生成器!
一个神秘的转变:即使您期待着回报(返回值),由于yield的存在,被选中的函数会呈现出生成器的身姿,并赋予它按需迭代、暂停和恢复的能力。
这是因为 Python 的函数定义的语义决定了在编译函数的时候解释器会如何处理它。
在 Python 中,函数如何行为取决于函数的定义而不仅仅是实际运行时的行为。当 Python 的编译器遇到一个函数定义时,它会检查函数体内的语句。如果它发现了 yield 关键字,不管这个 yield 是否在逻辑上可达(即不管它是否在 try 块还是 except 块,或者它是否在某个条件判断很少为真的代码分支中),它都会将这个函数标记为生成器函数。
这意味着一旦函数体中出现 yield,Python 就会创建生成器对象而不是直接执行函数体并返回单一的结果。
三、神秘仪式:为何print未被宣读?
这个生成器仪式的初次召唤(首次调用函数)并不意味着立即展现魔法(执行函数体内的代码),而是颁发一个神秘的标记(生成器对象)。这个标记,好像是一个尚未开启的宝箱,装载着即将展开的奇妙冒险。
迭代这个标记(调用生成器对象的next()方法),就像翻开宝箱的锁,魔法(函数体的代码)才会启动,直到遇到第一个yield魔法符(表达式)为止。
想要领略这段冒险,就请看以下的仪式演示:
def my_generator():print("开始执行")yield 1print("继续执行")yield 2print("执行结束")# 创建生成器对象
gen = my_generator()# 开始迭代生成器
next(gen)
# 输出:"开始执行"
# 在此时, 第一个 yield 1 表达式被执行, 并且函数的状态被暂停next(gen)
# 输出:"继续执行"
# 在此时, 第二个 yield 2 表达式被执行, 并且函数的状态再次被暂停next(gen)
# 输出:"执行结束"
# 函数执行到最后, 并且因为没有更多的 yield 表达式,迭代到此结束,
# 如果试图继续迭代,将抛出 StopIteration 异常。
这是因为生成器函数在首次被调用并返回生成器对象时,并不会执行任何函数体内部的代码,它只是返回一个生成器对象。这个生成器对象可以理解为一个有待执行的函数体。只有当你开始迭代这个生成器(即调用该生成器对象的 next() 方法)时,生成器函数的代码才会开始执行,直到遇到第一个 yield 表达
四、最终揭示
- 即使很隐秘,yield魔法符号的存在,会让一个函数被赋予生成器的身份。
- 魔法的初次召唤(生成器函数首次调用)仅仅是交付了一个未来冒险的符记(生成器对象),不触发任何神秘力量(不执行函数体内的代码)。
- 开启这个冒险(使用next()方法迭代生成器对象)才真正激活了仪式中的法术(函数体内的代码),并把我们引领至第一个法术停顿点(yield)。
相关文章:
深入探秘Python生成器:揭开神秘的面纱
一、问题起源: 想象一下,您掌握了一种魔法,在代码世界里,您可以轻松呼唤出一个整数。然而,事情并不总是看起来那样简单。在Python的奇妙王国中,我遇到了一个有趣的谜题: def tst():try:print(…...
红队攻防渗透技术实战流程:红队目标信息收集之批量信息收集
红队资产信息收集 1. 自动化信息收集1.1 自动化信息收集工具1.2 自动域名转换IP工具1.3 自动企业信息查询工具1.4 APP敏感信息扫描工具1.5 自动化信息工具的使用1.5.1 资产灯塔系统(ARL)1.5.1.1 docker环境安装1.2.2.9.1 水泽-信息收集自动化工具1. 自动化信息收集 1.1 自动化…...

【vue3学习笔记(二)】(第141-143节)初识setup;ref函数_处理基本类型;ref函数_处理对象类型
尚硅谷Vue2.0Vue3.0全套教程丨vuejs从入门到精通 本篇内容对应课程第141-143节 课程 P141节 《初识setup》笔记 1、setup是所有组合式API“表演的舞台”,组件中所用到的所有数据、方法、监视数据、生命周期钩子等都需要配置在setup中。 2、setup的两种返回值&…...

若依框架学习使用
若依官网项目拉取下来介绍 | RuoYi 项目运行: 1.idea安装,可以运行前后端 编辑器idea、jdk环境安装、数据库mysql、navicat工具、redis(redis-server启动)安装 2.navicat数据库连接, 创建数据库ry-vue并导入数据脚本ry_2021xxxx.sql,qua…...
蓝桥杯_数学模板
1.试除法判定质数 #include <iostream> using namespace std;bool is_zs(int x) {if(x<2) return false;for(int i2;i<x/i;i)if(x%i0)return false;return true; }int main() {int n; cin>>n;while(n--){int x; cin>>x;if(is_zs(x)) cout<<&quo…...

稀碎从零算法笔记Day31-LeetCode:接雨水
半月一去,望舒一轮,明天开始攻坚哈德题了 前言:非常经典的一道笔试题,看了保证血赚(今天银泰星笔试第四题就是这个) 题型:dp、模拟、双指针…… 链接:42. 接雨水 - 力扣ÿ…...
微前端的使用和注意事项 - qiankun
一、为什么使用微前端 微前端架构旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后,随之而来的应用不可维护的问题。微前端的核心目标是将巨石应用拆解成…...

uniapp微信小程序消息订阅详解
一、微信公众平台申请订阅模板 注意:订阅信息 这个事件 是 当用户 点击的时候触发 或者 是 支付成功后触发, 用户勾选 “总是保持以上选择,不再询问” 之后或长期订阅,下次订阅调用 wx.requestSubscribeMessage 不会弹窗…...
git 查看文件夹结构树
在Git中,没有直接的命令可以像文件系统那样展示一个可视化的文件结构树。但是,你可以使用一些外部工具或命令来达到这个目的。 以下是一些方法,你可以使用它们来查看Git仓库的文件结构树: 使用tree命令(如果你的系统已…...
设计模式一详解
一、观察者模式 当一个对象状态发生改变时,依赖它的对象全部会收到通知,并自动更新 场景:一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理逻辑。当更新的逻辑增多之后&#x…...

python 进程、线程、协程基本使用
1、进程、线程以及协程【1】进程概念【2】线程的概念线程的生命周期进程与线程的区别 【3】协程(Coroutines) 2、多线程实现【1】threading模块【2】互斥锁【3】线程池【4】线程应用 3、多进程实现4、协程实现【1】yield与协程【2】asyncio模块【3】3.8版本【4】aiohttp 1. 并发…...

SQLite3进行数据库各项常用操作
目录 前言1、SQLite介绍2、通过SQLite创建一个数据库文件3、往数据库文件中插入数据4、数据库文件信息查询5、修改数据库中的内容6、删除数据库中的内容 前言 本文是通过轻量化数据库管理工具SQLite进行的基础操作和一些功能实现。 1、SQLite介绍 SQLite是一个广泛使用的嵌入…...
Debian GNU/Linux 安装docker与docker compose
安装 Docker 更新包列表 sudo apt update 安装必要的软件包,以便让 APT 可以通过 HTTPS 使用存储库: sudo apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common 添加 Docker 的官方 GPG 密钥: cu…...
图片标注编辑平台搭建系列教程(2)——fabric.js简介
文章目录 综述数据管理图形渲染图形编辑事件监听预告 综述 fabric提供了二维图形编辑需要的所有基础能力,包括:数据管理、图形渲染、图形编辑和事件监听。其中,图形编辑可以通过事件监听和图形渲染来实现,所以可以弃用。数据管理…...

Debian linux版本下运行的openmediavault网盘 千兆网卡升级万兆
一、适用场景 1、使用vmware ESXi虚拟化平台运行多种不同应用服务器时,其中网盘服务器采用开源的openmediavault搭建; 2、将老专业服务器升级千兆网为万兆网; 3、需要转移的数据量大的企业或用户; 4、从服务器到服务器的数据转移…...

前端 CSS 经典:grid 栅格布局
前言:Grid 布局是将容器划分成"行"和"列",产生单元格,然后将"项目"分配给划分好的单元格,因为有行和列,可以看作是二维布局。 一 术语 1. 容器 采用网格布局的区域,也就是…...

多输入多输出通道
文章目录 图像卷积填充和步幅填充步幅 多输入多输出通道1x1卷积层 图像卷积 卷积原理: 就是将之前的大的图片,定义一个核函数,然后经过移动并运算将图片变小了.也就是将图像压缩提取整合特征值. 这里利用的时乘法. 填充和步幅 填充 在应用多层卷积时,我们常常…...

http响应练习—在服务器端渲染html(SSR)
一、什么是服务器端渲染(SSR) 简单说,就是在服务器上把网页生成好,整个的HTML页面生成出来,生成出的页面已经包含了所有必要的数据和结构信息,然后直接发给浏览器进行展现。 二、例题 要求搭建http服务&a…...
C++(8): std::deque的使用
1. std::deque std::deque 是 C 标准库中的一个双端队列容器。这个容器支持在序列的两端进行快速的插入和删除操作,其时间复杂度为常数时间 O(1)。同时,std::deque 也提供了对序列中任意元素的随机访问。 2. 特点 (1)双端操作&…...

openwrt开发包含路由器基本功能的web问题记录
1.这里的扫描怎么实现的先找一些luci代码,在openwrt21版本后,luci用js替换了lua写后台,先找一些代码路径 在openrwt15这部分代码是在这个目录下 feeds/luci/modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_join.htm 里面包含…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...