Python中 迭代( iteration )、迭代对象( iterable )、迭代器( iterator)、生成器(generator) 的关系详细讲解
(1). 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代。
只要是可迭代对象,无论有无下标,都可以迭代。使用for循环时,只要作用于一个可迭代对象,for循环就可以正常运行,而不太关心该对象究竟是list还是其他数据类型。
test1 = {'key1':2, 'key2':3, 'key3':4}
for key,value in test1.items(): # 遍历可迭代对象
print("key:" + key)
print("value:" + str(value))
(2). 判断一个对象是可迭代对象
使用dir()函数查看对象的属性列表,如果只有__iter__()函数则是可迭代的,如果__iter__()和__next__()函数都有则是迭代器 或者 使用isinstance() 函数来判断一个对象是否是一个已知的类型。
test1 = {'key1':2, 'key2':3, 'key3':4}
kv1 = test1.items()
from collections import Iterable, Iterator
print(isinstance(kv1, Iterable)) # 判断是不是可迭代对象
print(isinstance(kv1, Iterator)) # 判断是不是迭代器
(3). 生成器( generator )
如果列表元素可以按照某种算法推算出来,可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器。
① 只要把一个列表生成式的[ ]改成(),就创建了一个generator。
generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
L = [x*x for x in range(10)]
print(L) # 输出结果:[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
g = (x*x for x in range(10))
print(g) # 输出结果:<generator object <genexpr> at 0x00000180836FC1A8>
print(next(g)) # 输出结果:0
如果要输出生成器所有的元素,当生成器的元素比较多时候,不断的调用next()函数就太麻烦了。可以使用for循环,因为generator也是可迭代对象。创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
g = (x*x for x in range(10))
for i in g:
print(i, end=" ")
# 输出结果:0 1 4 9 16 25 36 49 64 81
② 如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。
最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。在执行过程中,遇到yield就中断,下次又继续执行。把函数改成generator后,基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代。
def fib(max):
'''
斐波拉契数列(Fibonacci),除第一个和第二个数外,
任意一个数都可由前两个数相加得到。
'''
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
for n in fib(6):
print(n)
用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value。
g = fib(6)
while True:
try:
x = next(g)
print('g:', x)
except StopIteration as e:
print('Generator return value:', e.value)
break
输出结果:
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done
(4). 迭代器
直接作用于for循环的对象统称为可迭代对象:Iterable。
生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了,可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。其实生成器就是迭代器。
把list、dict、str等Iterable变成Iterator可以使用iter()函数:
from collections import Iterable, Iterator
print(isinstance(iter([]), Iterator)) # 列表
print(isinstance(iter('abc'), Iterator)) # 字符串
print(isinstance(iter((1,2)), Iterator)) # 元组
print(isinstance(iter({1:2}), Iterator)) # 字典
print(isinstance(iter({1,2}), Iterator)) # 集合
可迭代对象不一定是迭代器,迭代器一定是可迭代对象。
迭代器:是一个可以记住遍历位置的对象,只能往前不会后退,有两个基本方法iter()、next()。字符串、列表或元组都可以用于创建迭代器。
Python的for循环本质上就是通过不断调用next()函数实现的。
推荐阅读
-
Python中 迭代( iteration )、迭代对象( iterable )、迭代器( iterator)、生成器(generator) 的关系详细讲解
-
Python中的生成器(generator)和迭代器(Iterator)
-
详解Python中的生成器和迭代器(generator和iterator)
-
一篇文章彻底搞懂Python中可迭代(Iterable)、迭代器(Iterator)与生成器(Generator)的概念
-
一篇文章彻底搞懂Python中可迭代(Iterable)、迭代器(Iterator)与生成器(Generator)的概念
-
Python中的迭代器(Iterator)与生成器(Generator)