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 ...
随机推荐
- Daily Scrum (2015/10/24)
由于这一天是周六,大家的学习热情依旧不是很高,但是在PM的要求和督促下,我们还是进行了一些工作.我们预计在明天(周日)完成全部的代码阅读工作,在下一周开始进行代码的编写工作,以下是我们的今日的工作情况 ...
- 《Spring2之站立会议1》
<Spring2之站立会议1> 昨天,查找了关于建立起服务器和客户端两端的连接的资料,并学习了如何写把两者建立起来的代码: 今天,模仿着相关资料,分别写了客户端和服务器两端的代码: 遇到的 ...
- P2P通讯原理
1.简介 当今互联网到处存在着一些中间件(MIddleBoxes),如NAT和防火墙,导致两个(不在同一内网)中的客户端无法直接通信.这些问题即便是到了IPV6时代也会存在,因为即使不需要NAT,但还 ...
- 第二次作业<1>
1001.A+B Format (20) ac代码 1. 解题思路 先求和,再输出. 答案区间为-2,000,000至2,000,000,将答案分为三个区段分类讨论.虽然觉得很烦但是想不出更好的方法. ...
- 关于Eclipse上使用可视化设计界面(Java EE 使用可视化界面设计)
Eclipse下可视化界面实现——WindowBulider安装 第一步: WindowBuilder官方下载安装说明地址:http://www.eclipse.org/windowbuilder/d ...
- 最近JavaScript的一些收获
开发习惯的上的收获 1,开发过程中,要让整个逻辑展示在一个函数中,中间部分则做可以考虑公用策略优化 2,开发完成至少有三个角度进行测试,正面方面和中立 开发技巧上面的收获 1,驼峰转为‘-’以及‘-’ ...
- [转帖] 学习一下 apache bench 的总结简介 ( LAMP的没用过..)
PS:网站性能压力测试是性能调优过程中必不可少的一环.只有让服务器处在高压情况下才能真正体现出各种设置所暴露的问题.Apache中有个自带的,名为ab的程序,可以对Apache或其它类型的服务器进行网 ...
- 安装iproute2
yum install -y gcc bison flex #tar -xzf iproute2-3.17.0.tar.gz #cd iproute2-3.17.0#sed -i '/^TARGET ...
- 绿色计算大赛决赛 第二阶段 消息传递(斯坦纳树 状压dp+spfa)
传送门 Description 作为公司老板的你手下有N个员工,其中有M个特殊员工.现在,你有一个消息需要传递给你的特殊员工.因为你的公司业务非常紧张,所以你和员工之间以及员工之间传递消息会造成损失. ...
- Django 2.0 学习(22):Django CSRF
Django CSRF CSRF攻击过程 攻击说明: 1.用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登陆网站A: 2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时 ...