Python中 迭代( iteration )、迭代对象( iterable )、迭代器( iterator)、生成器(generator) 的关系详细讲解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_37189082/article/details/100306955

(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()函数实现的。

猜你喜欢

转载自blog.csdn.net/qq_37189082/article/details/100306955