python 生成器和迭代器介绍
在正式接触生成器之前,我们先来了解一些概念
容器(container
)
容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个迭代获取,可以用in、not in关键字判断元素是否包含在容器中。通常这类数据结构把所有的元素存储在内存中(也有一些特殊的存在)。
Python中常见的容器对象:
- list ,deque, ...
- set, frozensets, ...
- dict, defaultdict, OrderedDict, Counter, ...
- tuple, nametuple, ...
- str
提示:1.可迭代对象赋予容器一种可以供提取元素的能力
2.不是所有的容器都是可迭代的
可迭代对象(iterable)
如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)。
可迭代对象并不局限于容器,如:files,sockets等(处于打开状态)。只要是可用i返回有一个可迭代的对象都可以称之为可迭代对象。
例:
x = [1, 2, 3]
y = iter(x) print(next(y))
print(next(y)) print(type(x), type(y))
分析:
这里x是一个可迭代对象,可迭代对象和容器一样是一种通俗的称呼,并不是指某种具体的数据类型。list,set,dict都是可迭代对象而y则是一个独立的迭代器,迭代器内部有一个状态,该状态用于记录当前迭代坐在的位置,以方便下次迭代的时获取正确的元素。
迭代器有一种具体的迭代器类型:list_iterator,set_iterator, ...。可迭代对象实现了__iter__()和__next__()方法(python2中是next()方法,python3.x是__next__()方法),这两个方法对应内置函数iter()和next()。__iter__方法返回可迭代对象本身,这使得它既有可迭代对象同时也是一个迭代器。
迭代器(iterator)
迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上像迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有机的统一起来。
迭代器具备以下两种方法:
- __iter__()
- __next__()
而可迭代对象必须具备:
- __iter__()
提示:1.对于迭代器来讲,有一个__next__()就够了。在使用for循环时,程序会自动调用即将被处理的迭代器对象,然后使用next()函数,直到检测到一个StopIteration异常。
2.next()内置函数就是调用对象的方法__next__(),iter()内置函数是调用对象的__iter__()方法。
案例:
- 直接调用next()方法
- 先使用iter(),再调用next()
上面的例子中,我们都知道列表 t 可以用 for 循环进行取值操作,但是不能被内置函数 next() 来取值,因此,判断 t 是 可迭代对象(iterable); 当 t 通过 iter() 进行包装后,可以调用 next() 查询取值,所以,I 是 迭代器(iterator)。
除了上述方式可以判断,还有collections模块的判断函数:
- 可迭代对象判断
- 迭代器判断
使用 iter() 将可迭代对象进行转化成迭代器
小结:我们可以推断,for 循环内部就是先调用 iter() 把 iterable 变成 iterator 再进行循环迭代。
上面的for循环和while循环等价
为什么list, dict, set, str等数据类型不是 迭代器(Iterator)?
因为Python的 Iterator 对象表示的是一个数据流,Iterator对象可以被next()内置函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration异常。可以把这个数据流看做是一个有序序列,但是不能提前知道这个序列的长度,只能不断通过next()内置函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时才会计算。Iterator可以看做是无限大的数据流,eg: 全体自然数,而list,set, str等是不可能存储全部的自然数的。
补充: Iterator继承自Iterable,从下面的测试中可以很方便的看到Iterator包含__iter__()和next()方法,而Iteratble仅仅包含__iter__()。
from collections import Iterator, Iterable
迭代器总结:
- 用for循环迭代的对象都是Iterable类型
- 用next()内置函数取值的对象都是Iterator类型,表示一个惰性计算的序列
- Iterable均可通过内置函数iter(),获得一个Iterator对象
- for循环内部实现机制
生成器
生成器的概念要比迭代器稍显复杂,因为生成器是能够返回一个迭代器的函数,其最大的作用是将输入对象返回为一个迭代器。Python中使用了迭代的概念,是因为当需要循环遍历一个较大的对象时,传统的内存载入方式会消耗大量的内存,不如需要时读取一个元素的方式更为经济快捷。
生成器是一次生成一个值的特殊类型函数(特殊的迭代器)。可以将其视为可恢复函数。调用该函数将返回一个可用于生成连续 x 值的生成器Generator。
有两点要先明确:
- 任意生成器都是迭代器(反之,不成立)
- 任意生成器,都是一个可以延迟创建值的工厂(可控性)
生成器的创建
- 将列表生成式中
[]
改成()
通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含百万元素的列表,不仅是占用很大的内存空间,如:我们只需要访问前面的几个元素,后面大部分元素所占的空间都是浪费的。
因此,没有必要创建完整的列表(节省大量内存空间)。在Python中,我们可以采用生成器:边循环,边计算的机制—>generator
我们该怎么打印元素呢?
刚刚提到生成器是特殊的迭代器,可以通过next()内置函数来获得generator的下一个返回值:
generator是保存的算法,每次调用next()内置函数,才能计算出下一个元素。
next的方式肯定不能用的,正因为generator也是可迭代对象,我们可以使用for循环。
提示:这里使用for循环,没有出现异常情况,是和迭代器一样的,都是因为for循环的内部机制。
简单的说就是在函数的执行过程中,yield语句会把你需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。
生成器小结:
- 生成器对象就是一种特殊的迭代器,满足迭代器协议,可以调用next()内置函数;对生成器for 循环时,调用iter()方法返回了生成器对象,然后再不断next()迭代,而iter()和next()都是在yield内部实现的。
- 生成器创建方式:常见两种(列表生成式、函数关键字)。
python 生成器和迭代器介绍的更多相关文章
- python 生成器和迭代器有这篇就够了
本节主要记录一下列表生成式,生成器和迭代器的知识点 列表生成器 首先举个例子 现在有个需求,看列表 [0,1,2,3,4,5,6,7,8,9],要求你把列表里面的每个值加1,你怎么实现呢? 方法一(简 ...
- 【转】python 生成器和迭代器有这篇就够了
总结得特别好,转自:https://www.cnblogs.com/wj-1314/p/8490822.html 本节主要记录一下列表生成式,生成器和迭代器的知识点 列表生成器 首先举个例子 现在有个 ...
- Python 生成器 (generator) & 迭代器 (iterator)
python 生成器 & 迭代器 生成器 (generator) 列表生成式 列表生成式用来生成一个列表,虽然写的是表达式,但是储存的是计算出来的结果,因此生成的列表受到内存大小的限制 示例: ...
- python 生成器,迭代器,闭包,装饰器
1.生成器,迭代器,闭包,装饰器的优点 生成器就是一类特殊的迭代器 迭代器的优点也即生成器的优点: 1.节约内存.python在使用生成器时对延迟操作提供了支持. 2.迭代到下一次的调用时,所使用的参 ...
- Python 生成器与迭代器 yield 案例分析
前几天刚开始看 Python ,后因为项目突然到来,导致Python的学习搁置了几天.然后今天看回Python 发现 Yield 这个忽然想不起是干嘛用的了(所以,好记性不如烂笔头.).然后只能 花点 ...
- Python生成器、迭代器、可迭代对象
把一个列表[]改成()就创建了一个生成器:generator,generator保存的是算法. 可以用于for循环的数据类型:1.集合类型:list tuple dict set str2.gener ...
- python 生成器和迭代器
迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stoplteration异常,以终止迭代(只能往后走不能往前退) 2.可迭代对象:实现了 ...
- Python生成器,迭代器,可迭代对象
在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list,set,dict ...
- python 生成器与迭代器(yield 用法)
背景 首先,我不会解释这两个名词,我看过很多遍解释,可还是看不懂,还是直接看使用情景吧. 我们以佩波拉契数列为例,当我们不知道迭代器的情况下,我们写出来的代码可能是这样子的: '''这种方式计算fib ...
随机推荐
- Spring的Controller映射规则
URL映射 1) 一般格式@RequestMapping(value=“/test”) 2) 可以使用模板模式映射,@RequestMapping(value=“/test/{userId}”) 3) ...
- 第三次实验报告 敏捷开发与XP实践
一. 实验内容 (一)敏捷开发与XP 摘要:一项实践在XP环境中成功使用的依据通过XP的法则呈现,包括:快速反馈.假设简单性.递增更改.提倡更改.优质工作.XP软件开发的基石是XP的活动,包括:编码 ...
- 《Spring 2之站立会议3》
<Spring 2之站立会议3> 昨天,查找了本机的端口号,并对代码作进一步的了解. 今天,对我们项目的基本框架进行了了解,即主界面和各个分界面的基本架构: 遇到的问题,虽然了解了基本框架 ...
- [usaco]2013-jan Liars and Truth Tellers 真假奶牛
Description 约翰有N头奶牛,有一部分奶牛是真话奶牛,它们只说真话,而剩下的是假话奶牛,只说假话.有一天,约翰从奶牛的闲谈中陆续得到了M句话,第i句话出自第Xi头奶牛,它会告诉约翰第Yi头是 ...
- PyCharm 配置远程python解释器和在本地修改服务器代码
PyCharm 配置远程python解释器和在本地修改服务器代码 最近在学习机器学习的过程中,常常需要将本地写的代码传到GPU服务器中,然后在服务器上运行.之前的做法一直是先在本地写好代码,然后通过F ...
- Beta阶段冲刺前的准备
Beta阶段冲刺前的准备 凡事预则立,在Beta开始前,以小组为单位,在敏捷冲刺前发布一篇博客,描述: 1. 讨论组长是否重选的议题和结论 经过我们小组在周二下午的会议中有重新认真的考虑了是否要更换组 ...
- psp本周
四人项目: 日期 类别 内容 开始时间 结束时间 中断时间 净时间 10.4 站立会议 站立会议报告 21:12 21:37 0 25 结对项目: 日期 类别 内容 开始时间 结束时间 中断时间 净时 ...
- Java 文件下载功能 解决中文乱码
Html部分 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...
- L2 L3 L4
第二层交换机,是根据第二层数据链路层的MAC地址和通过站表选择路由来完成端到端的数据交换的.因为站表的建立与维护是由交换机自动完成,而路由器又是属于第三层设备,其寻址过程是根据IP地址寻址和通过路由表 ...
- behavior
http://www.css88.com/book/css/properties/only-ie/behavior.htm 语法: behavior:<url> | url(#objID) ...