咱们都知道for in
在代码中出现的次数至关的频繁, 那么你知道for in
循环中到底发生了什么吗?html
答: 当咱们调用一个for x in dataContainer
的时候, 其实是先调用了dataContainer
的__iter__()
方法来得到它的iterator
(迭代器), 而后不断的调用next()
方法, Python3.x里面是__next__()
, 直到迭代器抛出StopIteration
的异常, 中止python
上一篇如何理解yield中已经对interable
已经略有介绍, 咱们能够简单的认为可使用for in
的都是iterable
的, 可是这只是从使用场景来讲的, 下面就从它内部来讲下segmentfault
iterable
: 若是一个数据容器定义了一个__iter__()
方法, 那么它就是可迭代的iterator
: 若是一个object
支持迭代协议
, 也就是: 1. 定义一个__iter__
返回它自身 2. 定义一个next()
方法, 每次被调用的时候返回下一个值很明显list
dict
是iterable
的, 但它不是iterator
app
>>> a = [1,2,3] >>> a.__iter__ <method-wrapper '__iter__' of list object at 0x2ad2cf8> >>> a.next() Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: 'list' object has no attribute 'next'
可是经过__iter__
得到的就是它们的iterator
迭代器code
>>> ai = a.__iter__() >>> ai <listiterator object at 0x2dfe310> >>> ai.next() 1 >>> ai.__iter__() is ai True
class MyList(list): def __iter__(self): return MyListIter(self) class MyListIter(object): """一个实现List的Iterator的 Demo Class""" def __init__(self, lst): self.lst = lst self.i = -1 def __iter__(self): return self def next(self): if self.i<len(self.lst)-1: self.i += 1 return self.lst[self.i] else: raise StopIteration if __name__ == '__main__': a = MyList([1, 2, 3, 4]) ia = iter(a) print 'type(a): %r, type(ia): %r' %(type(a), type(ia)) for i in a: print i,
上面的一段代码中 MyListIter
就实现了 MyList
的迭代器, 运行结果应该是htm
type(a): <class '__main__.MyList'>, type(ia): <class '__main__.MyListIter'> 1 2 3 4
好比咱们有一个需求, 须要返回全部0~4
中数字和a~e
中字母组合状况, 通常咱们可能会这样写blog
class Combinations: def __init__(self): self.combs = [] for x in range(5): for y in ['a', 'b', 'c', 'd', 'e']: self.combs.append("%s%s" % (x, y)) for c in Combinations().combs: print c
这样的话, 咱们每次都要调用Combinations
的'combs'才能拿到全部的组合状况, 显然每次暴露combs
出来很是的不优雅, 为何不能for c in Combinations()
这样呢?ip
固然能够, 定义一个__iter__
方法返回combs
的迭代器就能够了get
class Combinations: def __init__(self): self.combs = [] for x in range(5): for y in ['a', 'b', 'c', 'd', 'e']: self.combs.append("%s%s" % (x, y)) def __iter__(self): return iter(self.combs) for c in Combinations(): print c