python迭代器

for item in Iterable本质

在理解迭代器之前,先知道for item in Iterable的执行过程,注意,并不是说for迭代后面必须要一个可迭代对象
只要要迭代的对象能够调用iter()方法,正确返回迭代器即可

  1. 先通过iter()函数获取可迭代对象Iterable的 迭代器

2 . 通过获取到的迭代器不断调用该迭代器next()方法来获取下一个值并将其赋值给item

3 . 当遇到StopIteration的异常后循环结束

这里提及到Iterable需要有两个方法可以调用 iter()和next() 方法,这两个方法对应对象的两个魔法函数
__iter__以及__next____iter__要返回一个迭代器,__next__需要返回数据。下面来讲解这两个方法以及迭代器,可迭代对象的关系。

可迭代对象(Iterable)

Python中任意的对象,只要它定义了可以返回一个迭代器的__iter__方法。

>>>from collections import Iterator,Iterable
>>> class MyList(object):
...     def __init__(self):
...             self.container = []
...     def add(self, item):
...             self.container.append(item)
...     def __iter__(self):
...             """返回一个迭代器"""
...             # 我们暂时忽略如何构造一个迭代器对象
...             pass
...
>>> mylist = MyList()
>>> from collections import Iterable
>>> isinstance(mylist, Iterable)
True
>>>
# 这回测试发现添加了__iter__方法的mylist对象已经是一个可迭代对象了

isinstance(mylist, Iterable)可以判断是否是迭代器。
但是MyList对象还不能正常的工作,它虽然是一个可迭代对象但是并不能给for遍历,因为__iter__方法没有返回一个迭代器,需要__iter__返回一个迭代器。下面说一说迭代器如何实现。

迭代器(Iterator)

一个实现了__iter__方法和__next__方法的对象,就是迭代器。注:有些资料只说__next__方法,但是在pyhton3调用instance(Iterator)会返回False。
迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据,实际上,在使用next()函数的时候,调用的就是迭代器对象的__next__函数
所以,我们要想构造一个迭代器,就要实现它的__next__函数, 但是这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现iter方法,而iter方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的iter方法返回自身即可。
实现一个简单的迭代器:

class MyIterator(object):
    """自定义的迭代器"""
    def __init__(self, mylist):
        self.mylist = mylist
        # current用来记录当前访问到的位置
        self.current = 0
    def __next__(self):
        if self.current < len(self.mylist.items):
            item = self.mylist.items[self.current]
            self.current += 1
            return item
        else:
            raise StopIteration
    def __iter__(self):
        return self

用可迭代对象封装迭代器:

class MyList(object):
    """自定义的一个可迭代对象"""
    def __init__(self):
        self.items = []
    def add(self, val):
        self.items.append(val)
    def __iter__(self):
        myiterator = MyIterator(self)
        return myiterator

Iterator和Iterable两者关系

  • python3中可迭代对象(Iterable)是实现了__iter__方法就可以,迭代器(Iterator)是实现了__iter__方法和__next__方法的对象才可以,也就是说迭代器一定是可迭代对象,反过来不可。
  • 一个对象可以同时既是可迭代对象又是迭代器,只要方法里有__next__(python3) 又有__iter__方法,惯用的做法是__iter__方法返回自己作为迭代器。
  • 要给for遍历 需要对象实现__iter__方法并且正确返回一个迭代器。
  • 如果一个对象定义了可以支持下标索引的__getitem__方法也是可以被for…in…循环的,但是isinstance(Iterable)却是错误的
  • for…in…后面不一定是可迭代对象,__getitem__也可以

关于__getitem__和for迭代

是在类中定义了这个__getitem__方法,那么它的实例对象(假定为p),可以像这样
p[key] 取值,当实例对象做p[key] 运算时,会调用类中的方法__getitem__
一般如果想使用索引访问元素时,就可以在类中定义这个方法(__getitem__(self, key) )。
下面是一个例子:

class Mygetitem:
    def __init__(self, text):
        self.text = text
    def __getitem__(self, index):
        result = self.text[index].upper()
        return result
p = Mygetitem('Python')
for c in p:
    print(c)

__getitem__遇到异常时候终止for循环

isinstance(p, Iterable) = False

并不是可迭代对象,有些资料说可以被for迭代的就是可迭代对象我认为是不正确的。
Mygetitem是可以用iter(p)返回一个迭代器的。所以for迭代的本质是调用iter(Obj)得到一个迭代器,再调用里面的next()方法来

    原文作者:Baloneo
    原文地址: https://www.jianshu.com/p/fe4845e853ae
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞