文章目录

  • 迭代器
    • 1. 可迭代对象
    • 2. 迭代器
    • 3. 动手写一个可迭代的类
    • 4. 封装到一个类中
    • 5. 迭代器的应用
      • range和xrange
      • 使用迭代器生成斐波那契数列
      • 列表解析式
  • 生成器
    • 生成器的函数实现
    • 通过send方法从外向内给生成器传值

迭代器

1. 可迭代对象

from collections import Interable
print(isinstance([11,22,33],Interable))

如果要使一个对象是可迭代的,必须重写__iter__方法,这样才能通过Interable的检验,但是此时仍不能通过for函数遍历,所以仅仅是可迭代对象,而不是迭代器。

示例代码:

from collections.abc import Iterableclass ClassMate():def __init__(self) -> None:self.name = list()def add(self,name):self.name.append(name)def __iter__(self):passclassmate = ClassMate()
print("判断ClassMate是否是可迭代对象:",isinstance(classmate,Iterable))

2. 迭代器

迭代器必须重写__iter__方法和__next__方法,其中,__iter__方法必须返回一个对象的引用。

可以使用for循环遍历迭代器,for temp in xxx_obj的执行过程:

  1. 判断对象xxx_obj是否有__iter__方法(可迭代对象)
  2. 在第一步成立的条件下,调用iter函数,得到对象xxx_obj__next__的返回值,其返回值就是一个迭代器
  3. 自动调用迭代器的next函数,即调用迭代器的__next__方法,直到抛出StopIteration异常。

对于这样一个for循环

for i in seq:do_something_to(i)

实际上是这样工作的

fetch_iterator = iter(q)
while True:try:i = fetch_iterator.next()except StopIteration:breakdo_something_to(i)

迭代器非常重要,python3中字典、文件、列表都是可迭代的对象。

3. 动手写一个可迭代的类

from collections.abc import Iterable
from collections.abc import Iterator
# 实现将一个可迭代的类class ClassMate(object):def __init__(self) -> None:self.names = list()def add(self,name):self.names.append(name)def __iter__(self):# 返回一个迭代器的实例对象return ClassIterator(self)class ClassIterator(object):def __init__(self,obj):self.obj = obj# 通过实例属性记录前一次指针的位置self.current_num = 0def __iter__(self):passdef __next__(self):"""next方法执行此方法"""if self.current_num < len(self.obj.names):# 手动防止越界ret =  self.obj.names[self.current_num]self.current_num += 1return retelse:raise StopIteration# for 循环会自动捕获错误classmate = ClassMate()
classmate.add('小王')
classmate.add('小美')
classmate.add('小明')class_iterator = iter(classmate)print("判断classmate是否是可迭代对象",isinstance(classmate,Iterable))
print("判断class_iterator是否是迭代器",isinstance(class_iterator,Iterator))for name in classmate:print(name)# Output:
# 判断classmate是否是可迭代对象 True
# 判断class_iterator是否是迭代器 True
# 小王
# 小美
# 小明

执行过程:

注意:

  1. 可迭代对象A的__iter__返回一个迭代器的 实例对象B, 迭代器B初始化时需要将 可迭代对象A 传入 初始化方法;
  2. 迭代器实例对象通过一个 实例属性self.current_num记录当前读取的位置
  3. 需要手动防止越界,否则for语句会不断执行__next__,并捕获返回的None,此时,可通过抛出 StopIteration 错误,for循环会自动捕获。

4. 封装到一个类中

上面的方法使用了两个类,有点浪费资源,我们将其全部封装到一个类中

from collections.abc import Iterable
from collections.abc import Iterator
# 实现将一个可迭代的类class ClassMate(object):def __init__(self):self.names = list()self.current_count = 0def add(self,name):self.names.append(name)def __iter__(self):# 返回自身实例对象return selfdef __next__(self):if self.current_count<len(self.names):ret = self.names[self.current_count]self.current_count+=1return retelse:raise StopIterationclassmate = ClassMate()
classmate.add('小王')
classmate.add('小美')
classmate.add('小明')class_iterator = iter(classmate)print("判断classmate是否是可迭代对象",isinstance(classmate,Iterable))
print("判断class_iterator是否是迭代器",isinstance(class_iterator,Iterator))for name in classmate:print(name)# Output:
# 判断classmate是否是可迭代对象 True
# 判断class_iterator是否是迭代器 True
# 小王
# 小美
# 小明

5. 迭代器的应用

range和xrange

【补充】rangexrange的区别:

range和xrange的区别:在python2中range返回数值,xrange返回一个可迭代的对象,占用了极小的空间,

在python3中,range也返回的是一个可迭代对象了。

使用迭代器生成斐波那契数列

例如可以使用迭代器实现斐波那契数列

# 一般实现
a = 0
b = 1
i = 0
while i<10:a,b = b,a+bprint(a)
# 迭代器实现class  Fibonacci(object):def __init__(self,all_num):self.max_num = all_numself.count_num = 0self.a = 0self.b = 1def __iter__(self):return selfdef __next__(self):if self.count_num < self.max_num:self.count_num += 1self.a,self.b = self.b,self.a+self.breturn self.aelse:raise StopIterationfibo = Fibonacci(10)
for num in fibo:print(num)

列表解析式

列表解析,List comprehensinos,来自于Haskell语言,可以取代lambda、map和filter函数的部分使用场景。

语法[expr for iter_val in iterable if cond_expr]

例1:计算一个序列成员的平方

map(lambda x:x**2,range(6))
# 或者
[x**2 for x in range(6)]

例2:挑选出序列seq中的奇数

filter(lambda x: x%2,seq)
# or
[x for x in seq if x%2]

例3:计算文本中的单词个数【列表解析式支持多重循环和多个if语句,执行顺序从左到右】

f = open('test.txt','r')
len([word for line in f for word in line.split()])

生成器表达式和列表解析式很类似:(expr for iter_val in iterable if cond_expr),因为生成器表达式使用了“延迟计算”(lazy evaluation),所以在内存上比列表解析式更加有效。

生成器

生成器是一种特殊的迭代器,你只能对它迭代一次,因为它在运行时生成值,并不存储进内存。

生成器的函数实现

生成器由两种定义方式,第一种即是将列表解析式的[]换成(),不过更常用的是函数的形式:

例子:使用生成器生成斐波那契数列

def create_num(all_num):a,b = 0,1count_num = 0while count_num < all_num:yield a  a,b = b,a+bcount_num += 1
obj = create_num(10)
for i in obj:print(i)# 当执行到yield的时候,生成器会暂停输出,并返回结果

可见,生成器和函数的一个重要区别就是函数名()h会立即执行,而obj = 生成器()只是创建一个生成器对象,通过next obj的方式,返回内部yield对应的值,下次调用next的时候,则会从上次yield暂停的地方开始执行。

当然也可以使用while True的方式遍历生成器对象,但是 需要手动捕获异常 作为结束条件。

def create_num(all_num):a,b = 0,1count_num = 0while count_num < all_num:yield a  a,b = b,a+bcount_num += 1 obj = create_num(10)
while True:try:ret = next(obj)print(ret)except Exception as ret:print(ret.value)break

也可以创建多个生成器,互不影响,类似于类创建的对象之间的关系。

通过send方法从外向内给生成器传值

生成器的yield不仅能够将生成器内部的值传出来,还能够接收外部传送的数据,需要send方法传递。

demo:

def create_num(all_num):a,b = 0,1count_num = 0while count_num < all_num:ret_in = yield a  print(">>>ret>>>",ret_in)a,b = b,a+bcount_num += 1 obj = create_num(10)
ret_out = next(obj)
print(ret_out)ret_out = obj.send("hahahah")
print(ret_out)

首先,执行yield a,将a的值传递给ret_out,然后在send调用时,继续执行这一行,但是yield已经没有返回值,这里传递给ret_in的值,就是send中的参数。

注意:send不能在一开始处就调用,否则会报错。

小结:

拥有一个__iter____next__方法的类的实例对象叫做迭代器,可以节省内存空间;拥有yield的函数叫生成器,可以在yield处暂停执行,并在下次调用时从上次暂停的地方重新开始,两者都可以通过next进行遍历。

Python日积月累_6_迭代器+生成器相关推荐

  1. python自动化_day4_迭代器生成器内置函数和匿名函数

    什么是可迭代的 含有__iter__方法的就是可迭代的: python 可迭代对象--Iterable Python中经常使用for来对某个对象进行遍历,此时被遍历的这个对象就是可迭代对象, 像常见的 ...

  2. Python基础 day4 迭代器生成器 装饰器 Json pickle 数据序列化 软件目录结构规范 作业:ATM项目开发...

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 列表生成器 1.列表生成式,迭代器&生成器 列表生成式 孩子, ...

  3. python各种模块,迭代器,生成器

    从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能) 本质就是.py结尾的python文件(文件名:test.py,对应的模块名就是test) 包:用来从逻辑上组织模块的,本质就是一个目 ...

  4. python装饰器+迭代器+生成器

    1.函数嵌套:在调用一个函数的过程中,调用了其他函数 def f1():x=1def f2():print('from f2')f2() f1() 2.名称空间与作用域 a. 名称空间:存放名字与变量 ...

  5. python第四周迭代器生成器序列化面向过程递归

    第一节装饰器复习和知识储备------------ 第一节装饰器复习和知识储备------------ def wrapper(*args,**kwargs):index(*args,**kwargs ...

  6. python学习day-8 迭代器 生成器 装饰器

    http://www.cnblogs.com/linhaifeng/articles/7580428.html 迭代器#迭代器即迭代的工具,那什么是迭代呢?#迭代是一个重复的过程,每次重复即一次迭代, ...

  7. python 跳过异常元素继续,在python中的迭代器/生成器中引发异常后继续

    Is there any way in Python to continue iterating after exception throwed by iterator/generator? Like ...

  8. python迭代器两个基本方法可供参考_2018.8.10 python中的迭代器

    主要内容: 1.函数名的使用 2.闭包 3.迭代器 一.函数名的运用 函数名是一个变量,但他是一个特殊的变量,与括号配合可执行函数的变量. 1.函数名的内存地址 def func(): print(' ...

  9. python之路---迭代器和生成器

    阅读目录 楔子 python中的for循环 可迭代协议 迭代器协议 为什么要有for循环 初识生成器 生成器函数 列表推导式和生成器表达式 本章小结 生成器相关的面试题 返回顶部 楔子 假如我现在有一 ...

最新文章

  1. 基于OpenCV的视障人士实时目标检测
  2. SDCC 2016 中国软件开发者大会盛大开幕
  3. python hashlib模块
  4. 每天CookBook之JavaScript-016
  5. emacs-w3m查看html帮助手册
  6. python面向过程是基于面向对象的_Python5.1-面向对象与面向过程
  7. 耗时1年的前端技术框架切换之旅
  8. python大文件排序_Python如何实现大文件排序?Python大文件排序的实现方法
  9. Java + selenium 元素定位(3)之By TagName
  10. 利用二层端口安全防止两个三层交换机长距离光纤线路被乱接测试
  11. 计算机网络的分类 ppt,认识计算机网络ppt
  12. 使用Dism++和Dism为优启通08PE添加驱动
  13. 软件工程复习笔记 用例图
  14. Redis雪崩和Redis穿透
  15. 疫情期间大学生在线学习效果调查报告
  16. 查看php是否支持sg11,云虚拟主机支持SG11扩展
  17. RTD-Net:Relaxed Transformer Decoders for Direct Action Proposal Generation 论文阅读笔记
  18. 脚本小子_python基础
  19. Jquery获取与设置属性
  20. 网易云信IM小程序上线?我们是这么做的!

热门文章

  1. 八大排序(一):四种简单的排序(直接插入排序、希尔排序、冒泡排序、选择排序)
  2. 【洞见研报】研报速读:厨房小家电行业报告——“沙发经济”走向“厨房经济”(小家电,厨房小家电,厨房经济)
  3. 智慧医疗助力健康养老服务
  4. MySQL的优化,至尊奢华版
  5. 小学计算机走进智慧城堡教案,新苏教版二年级下册数学《千以内数的初步认识》教案教学设计...
  6. 通过 JFR 与日志深入探索 JVM - TLAB JFR 相关事件与日志详解
  7. 4g+uim卡是什么卡_uim卡是什么 sim卡槽能不能用uim卡
  8. windows刻录编程
  9. vue集成海康h5player实现播放
  10. Java对Json的一系列操作(构建、json与对象的转换)