Python中生成器和迭代器的区别详解
作者:ITxiaoke 发布时间:2022-12-04 02:32:08
Python中生成器和迭代器的区别(代码在Python3.5下测试):
Num01–>迭代器
定义:
对于list、string、tuple、dict等这些容器对象,使用for循环遍历是很方便的。在后台for语句对容器对象调用iter()
函数。iter()
是python内置函数。
iter()
函数会返回一个定义了next()
方法的迭代器对象,它在容器中逐个访问容器内的元素。next()
也是python内置函数。在没有后续元素时,next()
会抛出一个StopIteration异常,通知for语句循环结束。
迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据。实际上,在使用next()
函数的时候,调用的就是迭代器对象的_next_方法(Python3中是对象的_next_方法,Python2中是对象的next()
方法)。所以,我们要想构造一个迭代器,就要实现它的_next_方法。但这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现_iter_方法,而_iter_方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的_iter_方法返回自身self即可。
一些术语的解释:
1,迭代器协议:对象需要提供next()
方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代。
2,可迭代对象:实现了迭代器协议对象。list、tuple、dict都是Iterable(可迭代对象),但不是Iterator(迭代器对象)。但可以使用内建函数iter()
,把这些都变成Iterable(可迭代器对象)。
3,for item in Iterable 循环的本质就是先通过iter()
函数获取可迭代对象Iterable的迭代器,然后对获取到的迭代器不断调用next()
方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束
Python自带容器对象案例:
# 随便定义一个list
listArray=[1,2,3]
# 使用iter()函数
iterName=iter(listArray)
print(iterName)
# 结果如下:是一个列表list的迭代器
# <list_iterator object at 0x0000017B0D984278>
print(next(iterName))
print(next(iterName))
print(next(iterName))
print(next(iterName))#没有迭代到下一个元素,直接抛出异常
# 1
# 2
# 3
# Traceback (most recent call last):
# File "Test07.py", line 32, in <module>
# StopIteration
Python中一个实现了_iter_方法和_next_方法的类对象,就是迭代器,如下案例是计算菲波那切数列的案例
class Fib(object):
def __init__(self, max):
super(Fib, self).__init__()
self.max = max
def __iter__(self):
self.a = 0
self.b = 1
return self
def __next__(self):
fib = self.a
if fib > self.max:
raise StopIteration
self.a, self.b = self.b, self.a + self.b
return fib
# 定义一个main函数,循环遍历每一个菲波那切数
def main():
# 20以内的数
fib = Fib(20)
for i in fib:
print(i)
# 测试
if __name__ == '__main__':
main()
解释说明:
在本类的实现中,定义了一个_iter_(self)
方法,这个方法是在for循环遍历时被iter()调用,返回一个迭代器。因为在遍历的时候,是直接调用的python内置函数iter()
,由iter()通过调用_iter_(self)
获得对象的迭代器。有了迭代器,就可以逐个遍历元素了。而逐个遍历的时候,也是使用内置的next()函数通过调用对象的_next_(self)
方法对迭代器对象进行遍历。所以要实现_iter_(self)
和_next_(self)
这两个方法。
而且因为实现了_next_(self)
方法,所以在实现_iter_(self)
的时候,直接返回self就可以。
总结一句话就是:
在循环遍历自定义容器对象时,会使用python内置函数iter()
调用遍历对象的_iter_(self)
获得一个迭代器,之后再循环对这个迭代器使用next()
调用迭代器对象的_next_(self)
。
注意点: _iter_(self)
只会被调用一次,而_next_(self)
会被调用 n 次,直到出现StopIteration异常。
Num02–>生成器
作用:
>延迟操作。也就是在需要的时候才产生结果,不是立即产生结果。
注意事项:
>生成器是只能遍历一次的。
>生成器是一类特殊的迭代器。
分类:
第一类:生成器函数:还是使用 def 定义函数,但是,使用yield而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。
如下案例加以说明:
# 菲波那切数列
def Fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return '亲!没有数据了...'
# 调用方法,生成出10个数来
f=Fib(10)
# 使用一个循环捕获最后return 返回的值,保存在异常StopIteration的value中
while True:
try:
x=next(f)
print("f:",x)
except StopIteration as e:
print("生成器最后的返回值是:",e.value)
break
第二类:生成器表达式:类似于列表推导,只不过是把一对大括号[]
变换为一对小括号()
。但是,生成器表达式是按需产生一个生成器结果对象,要想拿到每一个元素,就需要循环遍历。
如下案例加以说明:
# 一个列表
xiaoke=[2,3,4,5]
# 生成器generator,类似于list,但是是把[]改为()
gen=(a for a in xiaoke)
for i in gen:
print(i)
#结果是:
2
3
4
5
# 为什么要使用生成器?因为效率。
# 使用生成器表达式取代列表推导式可以同时节省 cpu 和 内存(RAM)。
# 如果你构造一个列表(list)的目的仅仅是传递给别的函数,
# 比如 传递给tuple()或者set(), 那就用生成器表达式替代吧!
# 本案例是直接把列表转化为元组
kk=tuple(a for a in xiaoke)
print(kk)
#结果是:
(2, 3, 4, 5)
# python内置的一些函数,可以识别这是生成器表达式,外面有一对小括号,就是生成器
result1=sum(a for a in range(3))
print(result1)
# 列表推导式
result2=sum([a for a in range(3)])
print(result2)
来源:http://blog.csdn.net/u014745194/article/details/70176117
猜你喜欢
- 前言今天呢,笔者想和大家聊聊python+pytest接口自动化中将代码进行封装,只有将测试代码进行封装,才能被测试框架识别执行。例如单个接
- 前言最近有文字转图片的需求,但是不太想下载 APP,就使用 Python Pillow 实现了一个,效果如下:PIL 提供了 PIL.Ima
- 下面先给大家介绍下python获取酷狗音乐top500的下载地址 MP3格式,具体代码如下所示:# -*- coding: utf-8 -*
- 效果展示 准备工作1.canvas的使用主要用到了 bindtouchstart , bindtouchmove 两个属性,捕捉手
- 开发背景:最近在做一个批量数据导入到MySQL数据库的功能,从批量导入就可以知道,这样的数据在插入数据库之前是不会进行重复判断的,因此只有在
- 2D坐标系1 修改全部坐标颜色import matplotlib.pyplot as pltimport numpy as np#显示静态图
- 需求说明当用户申请售后,商家未在n小时内处理,系统自动进行退款。商家拒绝后,用户可申请客服介入,客服x天内超时未处理,系统自动退款。用户收到
- 如下所示: exitAct = QAction(QIcon('exit.png'), '&Exit'
- 1. 什么是文件指纹?文件指纹就是打包后输出的文件名的后缀,主要用来对修改后的文件做版本区分。2. 文件指纹有哪几种?1. Has
- 一,什么是JSON文件JSON和XML都是互联网上数据交换的主要载体。在JSON出现之前,大家一直用XML来传递数据。因为XML是一种纯文本
- 使用python的turtle库画一个方格和圆打开python编译器,导入turtle库from turtle import *首先画一个距
- 1 自动化测试自动化测试指软件测试的自动化,在预设状态下运行应用程序或者系统,预设条件包括正常和异常,最后评估运行结果。将人为驱动的测试行为
- 1、安装pymysql库如果你想要使用python操作MySQL数据库,就必须先要安装pymysql库,这个库的安装很简单,直接使用pip
- 一、设计理念1.先写一个登录的py文件,用python的tkinter库2.再写一个py文件用于爬取有道翻译输出栏的内容3.再利用pytho
- git还原到某次commit并强制推送远程不可逆提交一、reset1.git log查看提交记录git log2.选择某次提交的commit
- 一 计算公式:二 实现代码(1)import mathfrom tqdm import tqdmimport timetotal,s,n,t
- csv是Comma-Separated Values的缩写,是用文本文件形式储存的表格数据,比如如下的表格:就可以存储为csv文件,文件内容
- 昨天在网上找资料的时间无意进了一个站,糊里糊涂就进去了,想提权提不起来,后来加上服务商的Q号想社工一下,射了半天得知服务器的安全是绿盟的人给
- 前言昨天写小项目的时候遇到了一个需求:把txt文档的数据导入到mysql数据库中,开始本来想直接用Mysql Workbench导入TXT文
- 网页路径问题可以说是在页面设计或程序中比较典型的问题,处理得不好会给你的带来很大的麻烦,如何才能彻底解决路径问题呢!asp之家为你特别准备了