1、Iterable, 可迭代对象
概念:python中能够使用for循环遍历的都是可迭代对象
1、常见的可迭代对象:
1.1、序列如:list、str、tuple、range
1.2、非序列:dict、set、文件对象:f = open(xx)
1.2.1文件对象说明:
每次open一个文件时,这个文件就是一个可迭代对象,因为可以通过for循坏遍历获取文件的每一行
f = open('xxx文件','r',encoding = 'utf-8')
# 判断是否为可迭代对象,输出为True则为可迭代对象
print(isinstance(f, Iterable))
1.3、对象拥有__iter__()方法的任意对象(可迭代协议)
class MyClass1:
# 实现迭代协议
def __iter__(self):
return iter([11,22,33])
迭代协议(__iter__):
对象定义了一个__iter__方法的,那么这个对象就实现了迭代协议,__iter__方法的返回值必须是一个迭代器
# 1.3
# 当我们去遍历一个不是可迭代对象的类时,会报错提示"TypeError: 'Demo1' object is not iterable"
# class Demo1:
# pass
#
#
# d = Demo1()
# for i in d:
# print(i)
# 当我们在类中实现了__iter__()方法时,这个类就变成可迭代对象
class Demo2:
# 对象迭代时调用的方式
def __iter__(self):
return iter([11, 22, 33, 44])
d = Demo2()
for i in d:
print(i)
1.4、实现了序列语义的__getitem__()方法的任意对象。
class MyClass2:
value = [11,22,33]
# 实现迭代协议
def __getitem__(self,item):
return self.value[item]
注:实现了__iter__()方法或者__getitem__()方法都是可迭代对象,for循环会先去找是否有__iter__()方法,没有是才去找__getitem__()方法
# 1.4
li = ["aa", "bb", "cc"]
print(li[0]) # 实际执行为li.__getitem__(0),可以通过列表的源码看到
list()
class MyClass2:
value = [11, 22, 33]
# 实现迭代协议
def __getitem__(self, item):
return self.value[item]
d = MyClass2()
for i in d:
print(i)
2、Iterator, 迭代器
概念:实现了迭代器协议的对象 被称之为迭代器
1、迭代器协议:
迭代器协议由 `__iter__` 方法和`__next__`方法共同构成。实现了这两个方法的对象就实现了迭代器协议。
(迭代器的__iter__方法是从可迭代对象中继承来的)
2、实现了迭代器协议的对象,就是一个迭代器
3、所有的可迭代对象,都可以通过内置函数iter(转化为迭代器):
li = [11, 22, 33]
# 可迭代对象转换为迭代器:内置函数iter()
# 本质上是调用了可迭代对象的__iter__方法
# 传进去的是一个可迭代对象li,返回一个迭代器list_iterator
s = iter(li)# ===> iter(li) ===> li.__iter__()
4、迭代器对象能够使用内置函数next进行迭代操作(与可迭代对象的区别,有next()这个内置函数)
(每次迭代一个数据),当数据迭代完之后,会自动关闭迭代器
当迭代器关闭之后再使用next进行迭代,则抛出异常 StopIteration
注意点:迭代器中的数据 只能迭代一次(迭代完之后,迭代器就关闭了)
例如:
li = [11, 22, 33]
res = iter(li)
res1 = next(res)
print('res1:', res1)
res2 = next(res)
print('res2:', res2)
res3 = next(res)
print('res3:', res3)
res4 = next(res)
print('res4:', res4) # 抛出异常StopIteration
#注意点:
print('---以下的x不会被输出,因为迭代中的数据只能迭代一次------')
for x in res:
print(x)
# 2
li = [11, 22, 33]
# 可迭代对象转换为迭代器:内置函数iter()
res = iter(li) # ===> iter(li) ===> li.__iter__()
print(res) # 输出一个<list_iterator>,传进去的是一个可迭代对象,返回一个迭代器
# 迭代器可以使用next进行迭代操作
res1 = next(res)
print('res1:', res1)
res2 = next(res)
print('res2:', res2)
res3 = next(res)
print('res3:', res3)
# res4 = next(res)
# print('res4:', res4)
print('---以下的x不会被输出,因为迭代中的数据只能迭代一次------')
for x in res:
print(x)
3、Generator,生成器
应用层面的,学习之前需要先了解可迭代对象和迭代器。后续进行技术输出
处理大数据量时,使用生成器几乎不占内存。
因为生成器本身不存储数据,只存储数据迭代的规则
4、可迭代对象、迭代器、生成器的关系
# 关系:
from collections.abc import Iterable, Iterator, Generator
# 继承关系(生成器是儿子,迭代器是爸爸,可迭代对象是爷爷)
class Iterable(object):
pass
class Iterator(Iterable)
pass
class Generator(Iterator)
pass