• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
孙龙 程序员
少时总觉为人易,华年方知立业难
博客园    首页    新随笔    联系   管理    订阅  订阅
python Iterable和Iterator
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

posted on 2018-08-11 21:45  孙龙-程序员  阅读(145)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3