Python可迭代(Iterable)、迭代器(Iterator)和生成器(Generator)
admin
2024-03-28 03:08:47
0

可迭代对象 Iterable

可迭代对象(Iterable):一个对象只要实现了__iter__()方法,那么用isinstance()函数检查就Iterable对象。

例如:

class IteraObj:def __iter__(self):# 这里简单地返回自身# 但实际情况可能不会这么写# 而是通过内置的可迭代对象来实现# 下文的列子中将会展示return selfit = IterObj()
print(isinstance(it, Iterable))  # true
print(isinstance(it, Iterator))  # false
print(isinstance(it, Generator)) # false

常见的可迭代对象:

  1. 集合或序列类型,如list, tuple, set, dict, str
  2. 文件对象;
  3. 在类中定义 __iter__() 方法的对象;

自定义的Iterable对象,要满足在 for 循环中正确使用,必须保证 __iter__() 方法正确实现(可以通过内置 iter()函数将其转换成Iterator对象)。

  1. 在类中只定义 __getiem__() 方法的对象,可以通过 iter() 函数转化成 Iterator 对象。即 一个对象能够在 for 循环中运行, 但不一定是Iterable对象。

首先验证1,2

具体如下:

# 1. 
from collections import Iterable, Iterator
print(isinstance([], Iterable)) # true   list是可迭代的  
print(isinstance({}, Iterable)) # true   dict是可迭代的
print(isinstance((), Iterable)) # true   tuple是可迭代的
print(isinstance(set(),  Iterable)) # true  set是可迭代的
print(isinstance('', Iterable)) # true  str是可迭代的print(isinstance([], Iterator))  # False  
print(isinstance({}, Iterator))  # False  
print(isinstance((), Iterator)) # False  
print(isinstance(set(),  Iterator))  # False  
print(isinstance('', Iterator)) # False  # 2.
cur_path = os.path.dirname(os.path.abspath(__file__))
with open(cur_path + '/model.py') as f:print(isinstance(f, Iterable))  # trueprint(isinstance(f, Iterator))  # true# 3.
print(hasattr([], '__iter__'))  # true
print(hasattr({}, '__iter__'))  # true
print(hasattr((), '__iter__'))  # true
print(hasattr('', '__iter__'))  # true

结论:集合和序列对象是可迭代的但不是迭代器。

这些内置集合或序列对象都含有 __iter__属性,是Iterable对象。但它们要在 for 循环中被使用,就应该能够被内置的 iter() 函数调用并转化成 Iterator 对象。

例如:

print(iter([])) # 
print(iter({})) # 
print(iter(())) # 
print(iter('')) # 

这些内置集合或序列为Iterable对象, 都可以转换为对应的 Iterator对象。

其次验证3

再回头修改自定的 IterObj

class IterObj:def __init__(self):self.a = [3, 5, 7, 11, 13, 17, 19]def __iter__(self):return iter(self.a)it = IterObj()
print(isinstance(it, Iterable)) # true
print(isinstance(it, Iterator)) # false
print(isinstance(it, Generator)) # false
print(iter(it)) # 
for i in it:print(i) # 将打印3、5、7、11、13、17、19元素

结论:在定义一个Iterable对象是,要注意__iter__() 方法的内部实现逻辑, 一般情况下,利用一些已知的 Iterable对象(如集合、序列、文件等或其他正确定义的Iterable对象)来辅助我们实现。

最后验证4
iter()函数可以将一个实现了 __getitem__() 方法的对象转换成Iterator对象,但他不是 Iterable对象。

例子:

class IterObj:def __init__(self):self.a = [3, 5, 7, 11, 13, 17, 19]def __getitem__(self, i):return self.a[i]it = IterObj()
print(isinstance(it, Iterable)) # false
print(isinstance(it, Iterator)) # false
print(isinstance(it, Generator)) false
print(hasattr(it, "__iter__")) # false
print(iter(it)) # for i in it:print(i) # 将打印出3、5、7、11、13、17、19

结论:可以在 for 中使用的对象,不一定是可迭代对象。

综上所述

  1. 一个 Iterable 对象是实现了 __iter__() 方法的对象;
  2. 它要在 for 中循环使用,就必须满足 iter() 的调用(即调用这个函数不会出错,能正确转成一个 Iterator 对象)
  3. 可以通过已知的 Iterable 对象来辅助实现我们自定义的Iterable 对象。
  4. 一个对象实现了 __getiem__() 方法, 可以通过 iter() 函数转换成 Iterator 对象,即可以在 for 循环中使用,但它不是一个Iterable 对象。

迭代器 Iterator

定义: 一个对象实现__iter__()__next__()两个方法,那么它就是一个Iterator对象。
作用: 遍历集合元素。注意:只能从开头顺序访问至结尾。
特点:

  1. 迭代器:一个可以记住遍历位置的对象。→ 节省内容
  2. 迭代器:有两个基本方法:iter()next()
  3. 可迭代对象:可通过iter()方法构建迭代器。
form collections import Iterable, Iteratorl = [1,2,3,4,5] 
print(isinstance(l, Iterable))  # True 可迭代对象
print(isinstance(l, Iterator))  # False 不是迭代器 it = iter(l)   # 创建迭代器对象
print(isinstance(it, Iterable))  # True 可迭代对象
print(isinstance(it, Iterator))  # False 不是迭代器 #  1. next() 顺序遍历迭代器
print(next(it), end=" ")  #2. for() 循环遍历迭代器
for x in it:   print(x)
  1. 自定义迭代器
  • __iter__() 方法 → 起始位置
  • __next__() 方法 → 下一个,终止位置
from collections import Iterable, Iterator
# 构建一个可以反向输出的列表可迭代对象
class listDemo(object):def __init__(self):self.__data = []self.__num = 0def __iter__(self):return selfdef __next__(self):if self.__num <= 0:raise StopIteration  # 终止else:self.__num -= 1return self.__data[self.__num]def __setitem__(self, key, value):  # 插入self.__data.insert(key, value)self.__num += 1def __getitem__(self, index):  # 读取return self.__data[index]def __delitem__(self, index):  # 删除del self.__data[index]self.__num -= 1def __len__(self):return len(self.__data)mylist = listDemo()
mylist[0], mylist[1], mylist[2], mylist[3] = '1', '2', '3', '4'
print('Iterable:', isinstance(mylist, Iterable))
print('Iterator:', isinstance(mylist, Iterator))# 法1: 无需iter(), 因为该对象已为迭代器对象
print(next(mylist))
print(next(mylist))# 法2: 从当前迭代器位置 for循环
for i in mylist:print(i, end=" ")del mylist[2]
print(len(mylist))
print(type(mylist))

斐波那契迭代器
相关知识

class Fibonacci():  # 定义迭代器类def __init__(self):self.a = 0self.b = 1def __iter__(self):return selfdef __next__(self):if self.b > 100:raise StopIteration      # 结束条件else:self.a, self.b = self.b, self.a + self.breturn self.afib = Fibonacci()  # 实例化迭代器对象# for 循环
for f in fib:print(f, end=' ')

生成器

方式:

  1. 列表生成器 → 节省内存
  2. 使用·yield·定义生成器

特点:
一个生成器对象既是可迭代对象,也是迭代器对象。

验证方式1

from collections import Iterator, Iterable, Generator
g = (x * 2 for x in range(10))  # 0~18的偶数生成器
print(isinstance(g, Iterable))  # true
print(isinstance(g, Iterator))  # true
print(isinstance(g, Generator))  # true
print(hasattr(g, "__iter__"))  # true
print(hasattr(g, "__next__"))  # trueprint(next(g))  # 0
print(next(g))  # 2for x in g:print(x, end=' ')

验证方式2

  1. yield的作用相当于return,可通过next()函数或for循环遍历。
  2. 程序执行遇到yield关键字,生成函数返回当前值,继续向下执行。
def gen():for i in range(5):print('before')yield i  # 生成器函数print('after')print('end')it = gen()
print(list(it)) # 直接将生成器能生成的所有值存储成列表或者元组的形式it2 = gen()
print(next(it2))
print(it2.__next__())it3 = gen()
for i in it3:print(i, end=" ")

参考资料

一文彻底搞懂Python可迭代(Iterable)、迭代器(Iterator)和生成器(Generator)的概念

相关内容

热门资讯

一代人 顾城原文表达了作者什么... 一代人 顾城原文表达了作者什么情感,有何特殊意义一代人 顾城原文表达了作者什么情感,有何特殊意义《一...
为什么说竹是吉祥 富贵 平安的... 为什么说竹是吉祥 富贵 平安的象征竹子,四季常青,可以说是四季平安,吉祥。竹子节节升高,且寿命长,可...
突然一阵很大的声音会不会吓到龙... 突然一阵很大的声音会不会吓到龙猫呀.. 我家外婆说话声音很响..想知道会不会影响猫猫的健康不会的。。...
爱尔兰梗犬体态特征是什么,它应... 爱尔兰梗犬体态特征是什么,它应该怎么驯养呢?爱尔兰梗体态特征是优雅,外表漂亮。需要经常修剪和梳理披毛...
朽木充栋梁 番外 朽木充栋梁 番外《朽木充栋梁》(正文完结+番外全)发给你啦...
岳云鹏有部电影在电梯遇鬼的叫什... 岳云鹏有部电影在电梯遇鬼的叫什么电影《妖铃铃》
女朋友对篮球很感兴趣,应该怎样... 女朋友对篮球很感兴趣,应该怎样教她打篮球?可以首先带她了解球场规则,带她看球,然后开始练体能,必须要...
姓严的女孩子 要有三点水的,很... 姓严的女孩子 要有三点水的,很急,各位帮帮忙!谢谢啦~!7月28号生的·!严沅(yuan)媛(yua...
王心凌杨丞琳关系好吗? 王心凌杨丞琳关系好吗?她们是好朋友
好看的完结的青春校园小说 最好... 好看的完结的青春校园小说 最好是写明星的 或者不是也行 必须是完结的G小调进行曲3部,局外人,狼的诱...
稻草人的作家是谁 稻草人的作家是谁该作品的作者是叶圣陶。叶圣陶原名叶绍钧,江苏苏州人,是一位优秀的语言艺术家,不仅在教...
观《鹬》有感 观《鹬》有感  一颗沙子要经历风雨,才会成为珍珠;一个人只有坚持不懈,才会收获成功。今日,我偶观短片...
为什么秀禾不知道怀的耀辉孩子 为什么秀禾不知道怀的耀辉孩子在《橘子红了》这部剧中,秀禾并不知道她怀的是耀辉的孩子。虽然秀禾和耀辉相...
孔子嫁女儿,为什么选择一穷二白... 孔子嫁女儿,为什么选择一穷二白并且坐过牢的公冶长孔子嫁女儿,选择一穷二白并且坐过牢的公冶长,《论语》...
“雷同”一词源于何处? “雷同”一词源于何处?忽然想起~敬请诸位指教差点忘了`为何作相同的意思解?网络流行语呗,说的人多了就...
动物如何保护自己教案 动物如何保护自己教案动物如稿昌何保如敬锋护自己?教案可以告诉你,渣晌物竞天择,适者生存,这是每个动物...
孩子玩游戏“输不起”怎么办?家... 孩子玩游戏“输不起”怎么办?家长该如何纠正 只要输了,就会说话不算数。那么,家长该如何纠正孩子的...
求解(天狗吞月龙虎啸,贼人行窃... 求解(天狗吞月龙虎啸,贼人行窃在今期)打一生肖这是一句谜语,答案是“鸡”。“天狗吞月”是一个成语,形...
永劫无间怎么关语音 永劫无间怎么关语音永劫无间游戏中玩家们可通过语音与队友祥闹念进行交流,有的玩家可能误开了自由麦导致对...
火影穿越完结小说 火影穿越完结小说主角最好是男生,最好厉害一点;女生也行,不过主角要卡卡西,鼬或斑的。一定要完结,好的...