迭代器
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]