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)