from collections.abc import Iterable, Iterator
class Iterable(metaclass=ABCMeta):

__slots__ = ()

@abstractmethod
def __iter__(self):
while False:
yield None

@classmethod
def __subclasshook__(cls, C):
if cls is Iterable:
if any("__iter__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
class Iterator(Iterable):

__slots__ = ()

@abstractmethod
def __next__(self):
'Return the next item from the iterator. When exhausted, raise StopIteration'
raise StopIteration

def __iter__(self):
return self

@classmethod
def __subclasshook__(cls, C):
if cls is Iterator:
if (any("__next__" in B.__dict__ for B in C.__mro__) and
any("__iter__" in B.__dict__ for B in C.__mro__)):
return True
return NotImplemented

 判断是不是可以迭代,用Iterable

from collections import Iterable
isinstance({}, Iterable) --> True
isinstance((), Iterable) --> True
isinstance(100, Iterable) --> False


判断是不是迭代器,用Iterator

from collections import Iterator
isinstance({}, Iterator) --> False
isinstance((), Iterator) --> False
isinstance( (x for x in range(10)), Iterator) --> True


所以,


凡是可以for循环的,都是Iterable

凡是可以next()的,都是Iterator

集合数据类型如list,truple,dict,str,都是Itrable不是Iterator,但可以通过iter()函数获得一个Iterator对象

Python中的for循环就是通过next实现的

for x in [1,2,3,4,5]:
pass


等价于

#先获取iterator对象
it = iter([1,2,3,4,5])
while True:
try:
#获取下一个值
x = next(it);
except StopIteration:
# 遇到StopIteration就退出循环
break

 你可能会问,为什么list、dict、str等数据类型不是Iterator? 

这是因为Python的​​Iterator​​对象表示的是一个数据流,​​Iterator​​对象可以被​​next()​​函数调用并不断返回下一个数据,直到没有数据时抛出​​StopIteration​​错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过​​next()​​函数实现按需计算下一个数据,所以​​Iterator​​的计算是惰性的,只有在需要返回下一个数据时它才会计算。 

​Iterator​​甚至可以表示一个无限大的数据流,例如全体自然数。而使用​​list​​是永远不可能存储全体自然数的。

__iter__和__getitem__区别
from collections.abc import Iterable,Iterator

#可迭代对象
class Company(object):
def __init__(self,employee_list):
self.employee = employee_list

def __iter__(self):
print('hello')
return iter(self.employee)

def __getitem__(self, item):
print(item)
return self.employee[item]
if __name__ == '__main__':
company = Company(['sunlong','longsun','slong'])
for item in company:
print(item)
打印结果:

  hello

  sunlong

  longsun

  slong

 当for循环时候会先去找__iter__方法,上面__iter__方法中返回了一个迭代器,如果不是返回的迭代器 将会报错:

TypeError: iter() returned non-iterator of type 'NoneType'

如果不存在__iter__方法,接着会去调用__getitem__方法

假如删除__iter__方法,则会打印出:

0

sunlong

1

longsun

2

slong

3


自定义一个迭代器:

from collections.abc import Iterable,Iterator

#可迭代对象
class Company(object):
def __init__(self,employee_list):
self.employee = employee_list

def __iter__(self):
# return iter(self.employee)
return myItertor(self.employee)


#自定义迭代器
class myItertor():
def __init__(self,employee_list):
self.iter_list = employee_list
self.index = 0
def __next__(self):
#真正返回迭代值的逻辑
try:
word = self.iter_list[self.index]
except Exception :
raise StopIteration
self.index += 1
return word
def __iter__(self):
return self

if __name__ == '__main__':
company = Company(['sunlong','longsun','slong'])
# while True:
# try:
# print (next(my_itor))
# except StopIteration:
# pass
for item in company:
print(item)