表示可以逐一迭代或者遍历的对象,序列:列表、元组、集合、字符串。非序列:字典、文件。自定义对象:实现了__iter__()方法的对象;实现了使用整数索引的 getitem()方法的对象,这些都是可迭代对象。
iter() 用于定义该类的实例是可迭代对象,并且应该返回一个迭代器。当自定义类需要支持迭代时,就需要在类中定义 iter() 方法。
getitem()用于实现通过 obj[key] 来访问对象的方法,并且支持整数索引和切片。
通常情况下可以 isinstance(mobject, Iterable)判断实现了 iter()方法的可迭代对象,但是实现了__getitem__()方法的可迭代对象,不能使用isinstance 判断。这种的怎么判断呢?
官方文档描述:
https://docs.python.org/zh-cn/3.7/library/collections.abc.html#collections.abc.Iterable
from collections.abc import Iterable
class myiter:
pass
mi = myiter()
res = isinstance(mi, Iterable) # False 不是可迭代对象
print(res)
class myiterable:
data = [0, 1, 2, 3]
def __iter__(self):
return self.data
mi = myiterable()
res = isinstance(mi, Iterable) # True 是可迭代对象
print(res)
class mysequence:
data = [0, 1, 2, 3]
def __getitem__(self, index):
# 使用整数进行索引
return self.data[index]
ms = mysequence()
print(ms[3]) # 调用__getitem__方法,并且传递整数参数3
res = isinstance(ms, Iterable) # False 是可迭代对象 但是不能这样判断
print(res)
res = iter(ms) # 不报错,就说明是可迭代对象, iter()接受一个可迭代对象
print(res)
# 工程中的可迭代对象
# requests/models/Response 就是一个可迭代对象
# requests 的响应都是通过Response封装的
class Response(object):
def __iter__(self):
"""Allows you to use a response as an iterator."""
return self.iter_content(128)
import requests
response = requests.get('https://www.baidu.com')
res = isinstance(response, Iterable)
print(res) # True
# 将可迭代对象当参数的函数
data = [1, 2, 3, 4, '3']
iter(data)
map(int, data)
filter(lambda x: x > 0, data)
all(data)
any(data)
list(data)
tuple(data)
max(data)
min(data)
如果要实现一个迭代器,则必须遵循迭代器协议,即要支持两个方法:
iterator.iter() 返回迭代器本身
iterator.next() 要么返回迭代的下一项,要么触发StopIteration异常
迭代器是一个可以记住遍历位置的对象,从第一个元素开始访问,直到所有元素访问结束。
迭代器即实现了__next__()方法,又实现__iter__()方法。
使用 isinstance(mobject, Iterator)来判断
from collections.abc import Iterator
class myiterator:
pass
mi = myiterator()
res = isinstance(mi, Iterator) # False 不是迭代器
print(res)
class myiterator:
data = [0, 1, 2, 3]
def __iter__(self):
return iter(self.data)
mi = myiterator()
res = isinstance(mi, Iterator) # False 不是迭代器
print(res)
class myiterator:
data = [0, 1, 2, 3]
index = 0
def __iter__(self):
# 该方法 必须返回一个迭代器
# self本身实现了__iter__和__next__ 就是一个迭代器
return self
def __next__(self):
if self.index < len(self.data):
next_item = self.data[self.index]
self.index += 1
return next_item
else:
raise StopIteration
mi = myiterator()
res = isinstance(mi, Iterator) # True 是迭代器
print(res)
iter(mi)
res = next(mi) # 获取迭代器下一个元素
print(res)
import io
obj = io.StringIO('hello world!')
res = isinstance(obj, Iterator)
print(res)
data = [1, 2, 3, 4]
row = [5, 6, 7, 8]
# 哪些函数返回迭代器
print(isinstance(iter(data), Iterator))
print(isinstance(map(int, data), Iterator))
print(isinstance(filter(lambda x: x > 2, data), Iterator))
print(isinstance(zip(row, data), Iterator))
print(isinstance(enumerate(data), Iterator))
def iter_with_yield(x):
yield x
x -= 1
print(isinstance(iter_with_yield(4), Iterator))
可迭代对象,比如列表每次遍历都是从头开始,迭代器遍历后,会指向下一个位置,可迭代对象可以通过iter()函数包装成迭代器。
from collections import Iterable, Iterator
x = [1, 2, 3]
y = iter(x) # iter将列表x转换成生成器
hasattr(x, '__next__') # False 可迭代对象无__next__()方法
hasattr(y, '__next__') # True 迭代器有__next__()方法,可以使用next函数进行迭代
next(x) # 调用时会报错 TypeError: 'list' object is not an iterator
next(y) # 迭代器可以使用next进行迭代,获取下一个
isinstance(x, Iterable) # True 判断是否可迭代对象
isinstance(x, Iterator) # False 判断是否迭代器
isinstance(y, Iterable) # True 判断是否可迭代对象
isinstance(y, Iterator) # True 判断是否迭代器