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)
本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/articles/9461224.html