迭代对象
结论:
- 1、 拥有__iter___() 方法
items_lis = [1,2,3]
items_str = 'hello world'
from collections.abc import Iterator
from collections.abc import Iterable
print(isinstance(items_lis, Iterable)) # True 迭代对象
print(isinstance(items_lis, Iterator)) # False 迭代器
print(isinstance(items_str, Iterable)) # True 迭代对象
print(isinstance(items_str, Iterator)) # False 迭代器
- 可迭代对象之所以可以使用for循环,是因为在运行时,for循环会自动调用iter()方法,变为迭代器
- 比如我想获取列表中的值,但是不用for循环,怎么办,只能用while方法
- 之所以能用while,通过索引的方式输出,是因为列表(list)实现了__getitem__() 方法
列表同时有__item__() 和__getitem__() 会优先使用__item__()
当只有__getitem__(),使用for循环时,python解释器会自动生成默认的迭代器,然后这个迭代器会利用__getitem__来进行遍历
当只有__item__() 的时候,构建迭代器来输出,使用iter(),或者使用__next__()构建迭代器
# 不使用for循环,打印列表,是因为列表有 __getitem__() 方法
def iterator(item):
index = 0
try:
while True:
print(item[index])
index += 1
except:
print('数据已全部输出')
iterator(items_lis)
# 1
# 2
# 3
# 数据已全部输出
- 使用 iter() 方法构建迭代器,构建迭代器的时候,你得是可迭代对象,因为要遵守迭代器协议
- 下面可以使用next(),那是因为我是一个迭代器,迭代器有__next__() 方法
- 注释的print,两种,哪种都行
# 我照样不适用for循环,因为你只要是一个可迭代对象,for就给你后台自己创个迭代器出来
items_lis = [1,2,3]
items_lis_iter = iter(items_lis)
def iterator(item):
try:
while True:
print(next(item))
# print(items_lis_iter.__next__())
except:
print('数据都输出完了')
iterator(items_lis_iter)
# 1
# 2
# 3
# 数据都输出完了
- 当你是一个迭代对象,你用next(),或者__next__(),那指定报错
- 说我不是一个迭代器,哈哈哈哈,所以可迭代对象,那就是一个对象,要输出,还得靠迭代器
items_lis = [1,2,3]
print(next(items_lis))
Traceback (most recent call last):
File "F:/Py_Project/tools/3.py", line 14, in <module>
print(next(items_lis))
TypeError: 'list' object is not an iterator
迭代器
结论:
- 1、拥有__iter__() 方法
- 2、拥有__next__()方法
- 看上面对比说的,应该能懂一点吧
- 我直接构建一个迭代器吧,然后我在迭代器类里面没有写__iter__()方法,也可以运行,是因为迭代器有__iter__(),两个组合在一起了
class MyName: # 类 MyName 就是迭代对象
def __init__(self, name):
self.name = name
self.index = 0
def __iter__(self): # 迭代对象
return MyIterator(self.name) # 返回迭代器
class MyIterator: # 类 MyIterator 迭代器
def __init__(self, data):
self.iter_list = data
self.index = 0
def __next__(self): # 迭代器关键,这里写不写__iter__(),无所谓,因为迭代器有了
try:
iter_tar = self.iter_list[self.index]
except IndexError:
raise StopIteration
self.index += 1
return iter_tar
if __name__ == '__main__':
a = MyName(['a', 'b', 'c'])
# a = MyIterator(['a', 'b', 'c'])
for i in a:
print(i)
- 同样,我直接在一个类里面写了__iter__()和__next__(),我是可迭代对象,同时也是迭代器,
- 我直接在__iter__()里面return self,给自己return了,是因为我要自己当可迭代对象,return出去
- 搭配__next__()完成迭代器
class MyIterator:
def __init__(self, data):
self.iter_list = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
try:
iter_tar = self.iter_list[self.index]
except IndexError:
raise StopIteration
self.index += 1
return iter_tar
if __name__ == '__main__':
a = MyIterator(['a', 'b', 'c'])
for i in a:
print(i)
题外话:
因为在python的所有迭代场景中所作用的对象必须是可迭代对象(Iterable),因此迭代器(Iterator)要想在迭代场景中使用,就必须是Iterable对象;要成为Iterable对象就必须遵守Iterable协议,通过实现__iter__函数来满足Iterable协议,从而成为Iterable对象。个人认为,迭代器实现__iter_函数的目的是为了兼容python已有的迭代场景和工具,例如:for循环、列表解析、map、sum、zip等等。
如果迭代器不实现__iter_方法的话,上述函数和工具都无法用来对该迭代器进行迭代,只能通过人工调用next()方法来进行迭代,这与python “简洁统一” 的设计原则是相违背的,所以迭代器要实现__iter__方法。
直接看源码,就懂了
from collections.abc import Iterator
from collections.abc import Iterable