【Python基础】生成器

文章目录

    • @[toc]
      • 什么是生成器
      • 生成器示例
      • 生成器工作流程
      • 生成器表达式
      • `send()`方法和`close`方法
        • `send()`方法
        • `close()`方法

什么是生成器

  • Python中,使用生成器可以很方便地支持迭代器协议
  • 生成器通过生成器函数产生,通过def定义,但不是通过return返回,而是通过yield一次返回一个结果,在每个结果之间挂起和继续它们的状态,来实现迭代器协议
  • yield本质上是一个语法糖,内部是一个状态机,维护着挂起和继续的状态,从而支持迭代器协议

生成器示例

def my_range(n):i = 0while i < n:yield ii += 1my_range = my_range(3)print(my_range)print(next(my_range))
print(next(my_range))
print(next(my_range))
<generator object my_range at 0x0000019CE75804A0>
0
1
2
  • 在这个例子中,定义了一个生成器函数my_range()
  • 调用生成器函数会返回一个生成器对象,本质上是返回生成器对象的迭代器,通常直接称为生成器
  • 既然生成器本质上是一个迭代器,那么其内部需要实现__iter__()方法和__next__()方法,dir()函数可以获取一个对象的所有属性和方法,可以使用dir()函数查看生成器对象的属性和方法
def my_range(n):i = 0while i < n:yield ii += 1my_range = my_range(3)print(dir(my_range))print('__iter__' in dir(my_range))
print('__next__' in dir(my_range))
['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
True
True

生成器工作流程

  • 在上面的例子中加入一些打印信息,进一步看看生成器的工作流程
def my_range(n):print('开始迭代...')i = 0while i < n:print('迭代中...')yield iprint('-' * 10)i += 1print('迭代结束')gen_obj = my_range(3)print(next(gen_obj))
print(next(gen_obj))
print(next(gen_obj))
开始迭代...
迭代中...
0
----------
迭代结束
迭代中...
1
----------
迭代结束
迭代中...
2

1

  • 通过结果可以看到:
    • 当调用生成器函数的时候,函数只是返回了一个生成器对象,并没有运行
    • 当第一次调用next()方法的时候,生成器函数才开始运行,运行到yield语句处停止,并将i作为返回值返回,执行过程为图中的①
    • 当继续调用next()方法的时候,生成器函数从上一次停止的地方,也就是yield语句处继续运行,直到再次运行到yield语句处停止, 并将i作为返回值返回,执行过程为图中的②③
    • 如果下一次迭代不能运行到yield语句,就抛出StopIteration异常,生成器在当前yield语句处停止,不再执行②③过程

生成器表达式

  • 在介绍生成器表达式之前,先看看我们已经比较熟悉的列表解析
nums = [i for i in range(10) if i % 2]print(nums)
[1, 3, 5, 7, 9]
  • 上述列表解析返回一个包含 1 1 1 10 10 10之间所有奇数的列表
  • 当序列很长,而每次只需要获取一个元素时,应当考虑生成器而不是列表解析
  • 生成器表达式的语法和列表解析一样,只不过生成器表达式是被()括起来的
gen_obj = (i for i in range(10) if i % 2)print(gen_obj)
<generator object <genexpr> at 0x000001D6DC1E04A0>
  • 生成器表达式并不是返回一个列表,而是返回一个生成器
  • 使用生成器时,每迭代一次会产生(yield)出一个值来,实现了惰性加载(懒加载),只有在被迭代时才被赋值,并覆盖上一个值,所以在序列较长的情况下,使用生成器会优化内存

send()方法和close方法

  • 生成器中有两个重要的方法:send()方法和close方法
send()方法
  • Python 2.5中,yield语句变成了yield表达式,也就是说yield可以有一个值,而这个值就是send()方法的参数,通过调用send()方法将值传递给yield,而send()的返回值为yield返回的值,所以send(None)next()是等效的
  • 注意,调用send()传入非None值前,生成器必须处于挂起状态,否则将抛出异常,也就是说,第一次运行生成器时,只能使用next()send(None),因为没有yield来接收这个值
def my_range(n):i = 0while i < n:var = yield iprint(f'var 的值为 {var}')i += 1my_range = my_range(3)print(my_range.send(None))
print(my_range.send('hello'))
print(my_range.send('world'))
0
var 的值为 hello
1
var 的值为 world
2
close()方法
  • close()方法用于关闭生成器,对关闭后的生成器再次调用next()send()将抛出StopIteration异常
def my_range(n):i = 0while i < n:var = yield iprint(f'var 的值为 {var}')i += 1my_range = my_range(3)print(my_range.send(None))
print(my_range.send('hello'))my_range.close()print(my_range.send('world'))
0
var 的值为 hello
1
Traceback (most recent call last):File "C:/Users/FOLLOW_MY_HEART/Desktop/Python基础/【Python基础】迭代器/test.py", line 18, in <module>print(my_range.send('world'))
StopIteration

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/230520.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

亚马逊云科技re:Invent推出生成式AI技术堆栈及关键服务和工具

亚马逊云科技于29日推出“生成式AI技术堆栈”后&#xff0c;又在30日的re:Invent 2023大会上宣布了一系列支持这一全新堆栈的关键服务和工具。 亚马逊云科技数据和人工智能副总裁Swami Sivasubramanian在主题演讲中&#xff0c;将生成式人工智能与“超新星爆炸”进行了比较&am…

Python计算圆的面积,几何学技法大解析!

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;我是彭涛&#xff0c;今天为大家分享 Python计算圆的面积&#xff0c;几何学技法大解析&#xff0c;全文3800字&#xff0c;阅读大约15分钟。 在本文中&#xff0c;将深入探讨如何使用 Python 计算圆的面积&…

css画饼图

<template slot-scope"scope"> <div class"pie" :style"{--p: scope.row.rate}" style"--p:10;--b:10px;--c:#FFAB79;"> <!-- --p&#xff1a;这个变量应该包含百分比值作为一个数字&#xff08;不带%符号&#xff09;…

深入理解Python装饰器:丰富函数功能的强大工具

导语&#xff1a;装饰器是Python非常强大的功能之一&#xff0c;它们允许程序员修改或增强已有函数或方法的行为&#xff0c;而无需更改其本身的代码&#xff0c;这篇文章&#xff0c;让我们一起来看看&#xff08;我自己这里理解的也不是很透彻&#xff09; ----------更正---…

ansible远程操作主机功能和自动化运维

ansible 两个功能&#xff1a;1、远程操作主机功能 2、自动化运维&#xff08;play 剧本 yaml&#xff09; 简述&#xff1a; 是基于python开发的配置管理和应用部署工具。在自动化运维中&#xff0c;现在是异军突起。 Asible能批量配置&#xff0c;部署&#xff0c;管理上千…

【从零开始学习JAVA集合 | 第一篇】深入解读HashMap源码(含面试题)

目录 目录 前言&#xff1a; HashMap简介&#xff1a; HashMap的常用常量和变量&#xff1a; HashMap的重要考点&#xff1a; HashMap的存储过程&#xff1a; HashMap的扩容过程&#xff1a; HashMap的初始化&#xff1a; 常见面试题&#xff1a; 总结&#xff1a;…

AI摄影绘画与PS优化:重塑数字艺术的未来

文章目录 《AI摄影绘画与PS优化从入门到精通》内容简介作者简介楚天 目录前言/序言 在科技日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;已经渗透到我们生活的各个领域&#xff0c;包括艺术创作。AI摄影绘画和Photoshop&#xff08;PS&#xff09;优化是这个领…

「Verilog学习笔记」交通灯

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1nsmodule triffic_light(input rst_n, //异位复位信号&#xff0c;低电平有效input clk, //时钟信号input pass_request,output wire[7:0]clock,output reg…

使用Alpha Vantage API和Python进行金融数据分析

Alpha Vantage通过一套强大且开发者友好的数据API和电子表格&#xff0c;提供实时和历史的金融市场数据。从传统资产类别&#xff08;例如股票、ETF、共同基金&#xff09;到经济指标&#xff0c;从外汇汇率到大宗商品&#xff0c;从基本数据到技术指标&#xff0c;Alpha Vanta…

扫雪铲冰,绿萝护航平安出行

为保护行人出行安全&#xff0c;确保道路干净整洁&#xff0c;绿萝党员志愿者带头行动&#xff0c;号召志愿者积极参与扫雪铲冰。2023年12月16日&#xff0c;绿萝志愿服务队与拱辰集体林场携手在昊天碳中和公园开展了志愿扫雪活动。 行动是最好的融雪剂。大雪过后的道路是最为寒…

自动驾驶TPM技术杂谈 ———— 交通事件分类与编码

文章目录 介绍交通事件分类交通事件分类顺序码交通事故交通灾害交通气象路面状况道路施工活动重大事件其他 介绍 1. 交通事件 —— 由于人、车辆、设施、环境之间的不协调导致正常交通秩序的突发性混乱事件。  2. 交通管制 —— 公安机关交通管理部门根据法律、法规&#xff0…

2.1 数据操作

声明&#xff1a; 注意&#xff01;&#xff01;&#xff01; 本博客仅用于本人学习笔记作用&#xff0c;所有资料来源都来自于李沐大神&#xff0c;博客中图片为沐神书上的图片。如有侵权&#xff0c;请联系本人删除&#xff0c;谢谢。 资料来源&#xff1a;https://zh-v2.d2…

什么是通讯芯片?通讯芯片又分什么种类?

通讯芯片是指在通讯系统中起到连接和传输信号的重要组成部分。根据通讯芯片的功能和应用,可以将其分为以下几类: 1、收发器芯片 2、窄带中频放大器芯片 3、卫星接收器LNB芯片 4、电话机芯片 5、压缩扩展器芯片 以上是通讯芯片的一些分类&#xff0c;随着通讯技术的不断发展…

patchless amsi学习(中)

DR7 DR7被称为“调试控制寄存器”&#xff0c;允许对每个硬件断点进行精细控制。其中&#xff0c;前8位控制是否启用了特定的硬件断点。偶数位&#xff08;0、2、4、6&#xff09;称为L0-L3&#xff0c;在本地启用了断点&#xff0c;这意味着仅在当前任务中检测到断点异常时才…

接口自动化测试实战教程

实现思路 使用excel管理用例用例信息&#xff0c;requests模块发送http请求&#xff0c;实现了记录日志&#xff0c;邮件发送测试报告的功能 目录结构如下&#xff1a; 下面直接上代码&#xff1a; 统筹脚本 # -*- coding:utf-8 -*-import osfrom interface import Interfa…

Android Termux安装MySQL数据库并通过内网穿透实现公网远程访问

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…

【MongoDB】--MongoDB的Sort排序问题

目录 一、问题背景描述1.1、问题背景1.2、问题分析 二、建立索引支持深度翻页查询2.1、调整sort排序的内存限制【不建议】2.2、创建索引2.3、拓展--组合索引什么时候失效 二、聚合查询解决深度翻页查询 一、问题背景描述 1.1、问题背景 现实系统页面翻页到20000页之后&#x…

Improving IP Geolocation with Target-Centric IP Graph (Student Abstract)

ABSTRACT 准确的IP地理定位对于位置感知的应用程序是必不可少的。虽然基于以路由器为中心(router-centric )的IP图的最新进展被认为是前沿的,但一个挑战仍然存在:稀疏IP图的流行(14.24%,少于10个节点,9.73%孤立)限制了图的学习。为了缓解这个问题,我们将目标主机(ta…

【LeetCode刷题笔记(8-2)】【Python】【接雨水】【单调栈】【困难】

文章目录 引言接雨水题目描述提示 解决方案2&#xff1a;【单调栈】结束语 【接雨水】 【LeetCode刷题笔记&#xff08;8-1&#xff09;】【Python】【接雨水】【动态规划】【困难】 引言 编写通过所有测试案例的代码并不简单&#xff0c;通常需要深思熟虑和理性分析。虽然这…

200kw直流电子负载测试

在进行200kw直流电子负载测试时&#xff0c;需要设置合适的负载参数&#xff0c;如电流、电压和功率等&#xff0c;并记录测试结果。在测试过程中&#xff0c;可以通过改变负载参数来模拟不同工作条件下的电子设备的性能。通过对电子设备在不同负载条件下的响应进行测试和分析&…