首页 > 代码库 > 迭代器与生成器

迭代器与生成器

迭代器


Iterable

定义

 1 class Iterable(metaclass=ABCMeta):
 2 
 3     __slots__ = ()
 4 
 5     @abstractmethod
 6     def __iter__(self):
 7         while False:
 8             yield None
 9 
10     @classmethod
11     def __subclasshook__(cls, C):
12         if cls is Iterable:
13             if any("__iter__" in B.__dict__ for B in C.__mro__):
14                 return True
15         return NotImplemented

由定义可知Iterable必然包含__iter__函数

Iterator

定义

 1 class Iterator(Iterable):
 2 
 3     __slots__ = ()
 4 
 5     @abstractmethod
 6     def __next__(self):
 7         Return the next item from the iterator. When exhausted, raise StopIteration
 8         raise StopIteration
 9 
10     def __iter__(self):
11         return self
12 
13     @classmethod
14     def __subclasshook__(cls, C):
15         if cls is Iterator:
16             if (any("__next__" in B.__dict__ for B in C.__mro__) and
17                 any("__iter__" in B.__dict__ for B in C.__mro__)):
18                 return True
19         return NotImplemented

从定义可知Iterator包含__next____iter__函数,当next超出范围时将抛出StopIteration事件

类型关系

 

 1 #! /usr/bin/python
 2 #-*-coding:utf-8-*-
 3 
 4 from collections import Iterator,Iterable
 5 
 6 # 迭代器
 7 s = abc
 8 l = [1,2,3]
 9 d=iter(l)
10 
11 print(isinstance(s,Iterable)) # True
12 print(isinstance(l,Iterable)) # True
13 
14 print(isinstance(s,Iterator)) # False
15 print(isinstance(l,Iterator)) # False
16 
17 print(isinstance(d,Iterable)) # True
18 print(isinstance(d,Iterator)) # True

理论上你可以使用next()来执行__next__(),直到迭代器抛出StopIteration 实际上系统提供了for .. in ..的方式来解析迭代器

 

1 l = [1,2,3,4]
2 for i in l:
3     print(i)
4     
5 # 执行结果    
6 # 1
7 # 2
8 # 3
9 # 4

 

生成器 generator


 生成器的本质是一个迭代器

 

 1 #! /usr/bin/python
 2 #-*-coding:utf-8-*-
 3 
 4 from collections import Iterator,Iterable
 5 
 6 s = (x*2 for x in range(5))
 7 print(s)
 8 print(Is Iterable: + str(isinstance(s,Iterable)))
 9 print(Is Iterator: + str(isinstance(s,Iterator)))
10 
11 for x in s:
12     print(x)
13 
14 # 执行结果    
15 # <generator object <genexpr> at 0x000001E61C11F048>
16 # Is Iterable:True
17 # Is Iterator:True
18 # 0
19 # 2
20 # 4
21 # 6
22 # 8

函数中如果存在yield 则该函数是一个生成器对象 在每一次执行next函数时该函数会在上一个yield处开始执行,并在下一个yield处返回(相当于return

 

 1 def foo():
 2     print("First")
 3     yield 1
 4     print("Second")
 5     yield 2
 6 
 7 f = foo()
 8 print(f)
 9 
10 a = next(f)
11 print(a)
12 b = next(f)
13 print(b)
14 
15 # <generator object foo at 0x0000020B697F50F8>
16 # First
17 # 1
18 # Second
19 # 2

实例

 1 #! /usr/bin/python
 2 #-*-coding:utf-8-*-
 3 
 4 def add(s,x):
 5     return s+x
 6 
 7 def gen():
 8     for i in range(4):
 9         yield i
10 
11 base = gen()
12 
13 # 由于gen函数中存在yield,所以
14 # for 循环本质是创建了两个generator object,而非执行函数
15 # base = (add(i,10) for i in base)
16 # base = (add(i,10) for i in base)
17 for n in [1,10]:
18     base = (add(i,n) for i in base)
19 
20 
21 # 这里才开始展开生成器
22 # 第一个生成器展开
23 # base = (add(i,10) for i in base)
24 # base = (add(i,10) for i in range(4))
25 # base = (10,11,12,13)
26 #
27 # 第二个生成器展开
28 # base = (add(i,10) for i in (10,11,12,13))
29 # base = (20,21,22,23)
30 print(list(base)) # [20,21,22,23]

 

迭代器与生成器