小结-Python-可迭代、迭代器和生成器的区别

可迭代对象

可迭代对象指的是定义了_ _ iter _ _ 方法的对象,调用该方法会返回一个迭代器对象。

可迭代对象,例如:list列表、tuple元组、带有上述iter方法的对象等等。

# -*- coding: utf-8 -*-
from collections.abc import Iterable
from collections.abc import Iterator
# list的创建可以用list()函数和元组构建;也可以用[]和元素构成
a = list((1, 3, 5))
b = [2, 4, 6]
print(type(a), type(b))
# Output:    

# 可见,list列表是一个可迭代对象,但不是一个迭代器;
# 也可以进入list函数中查看没有__next__方法,只有一个__iter__方法。
x = isinstance(a, Iterable)
y = isinstance(a, Iterator)
print(x, y)
# Output:   True False

# 正因为,list是一个可迭代对象,所以可以用for循环遍历
for i in a:
    # Output:   1 3 5
    print(i, end=' ')
print(" ")

# 回忆以往常用的range函数就是一个可迭代对象,
# 因为进入函数内部同样没有__next__方法,只有一个__iter__方法。
for j in range(1, 10, 2):
    # Output:   1 3 5 7 9
    print(j, end=" ")

个人理解:在可迭代对象中使用for循环,实际上就是调用iter()--

迭代器

定义

迭代器就是定义_ _ next _ _ 方法的对象。每次调用上述方法就返回迭代器一个值,没有就抛出StopIteration异常。

创建

迭代器可以由可迭代对象通过内置函数iter()函数实现,该函数会接受一个可迭代对象,返回一个迭代器对象。实际上,iter()函数内部调用可迭代对象的——iter——方法。而前面在可迭代对象中就提到,该方法会返回一个迭代器对象。

小结:可迭代对象转化成为迭代器仅需要一个iter函数,其实质还是调用可迭代对象内部的——iter——方法去返回一个可迭代对象。

应用

迭代器如何应用?其实调用Python内置函数next函数就可以,该函数会接受一个迭代器对象,返回迭代器对象的下一个值。实际上,next()函数在内部调用了迭代器对象的——next——方法。

小结:迭代器其实多定义了一个——next——方法的可迭代对象,然后通过iter函数调用自己——iter——方法返回迭代器,让迭代器不仅可以可以for循环遍历,也可以通过next函数来访问下一个值。

注意分清:__iter__方法,__next__方法;内置函数iter(),内置函数next()

所以当有一个迭代器对象的时候,就不仅可以for循环遍历,也可以通过next函数访问下一个输出。

# 接前面代码,继续!
# 通过iter函数将可迭代对象转化成为迭代器。
a_iter = iter(a)
print(isinstance(a_iter, Iterable), isinstance(a_iter, Iterator))
# Output:   True True

# 然后使用next函数访问下一个值
print(next(a_iter))
# Output:   1

# 这个比较有趣,发现可迭代对象一旦调用next函数,则值访问就减少一次。
for i in a_iter:
    # Output:   3 5
    print(i, end=" ")
# print(next(a_iter))   Output:抛出异常,StopIteration 因为没有下一个值。

注意

这里解释一下,为何可迭代对象和迭代器都可以通过for循环迭代元素。

这是因为for循环对象要求一定要是可迭代对象!

所以可迭代对象可以进行for循环,而可迭代对象通过iter函数生成的迭代器也可以for循环。

因为在for循环内部,首先会调用iter函数,将需要遍历的对象(可迭代对象)转变成迭代器,然后在迭代器上重复调用next函数,直到抛出异常。

生成器

生成器的基本功能就是用来创建迭代器,形式上类似于普通定义函数,拥有yield关键字。

yield关键字不同于return,return后会推出相关代码,但yield则会保留退出,下次继续。

# 接上面代码,继续!
# 定义一个生成器,其形式类似函数定义,且拥有关键字yield
def generator_test():
    yield 1
    yield 2
    yield 3


g = generator_test()
# Output:   
print(type(g))

# 可见,生成器内部拥有以下两个方法,自然依据定义,生成器既是可迭代对象,也是迭代器。
print(hasattr(g, '__iter__'), hasattr(g, '__next__'))
# Output:  True True

# 既然是迭代器,那自然可以通过next函数访问下一个值,也可以for循环遍历。
print(next(g))
# Output:   1
for i in g:
    # Output:   2   3
    print(i, end=" ")

关系图

小结-Python-可迭代、迭代器和生成器的区别_第1张图片
屏幕快照 2019-05-05 21.36.33.png
  1. 迭代器一定是一个可迭代对象,因为既有可迭代对象的iter方法,也有可迭代对象不具备的next方法。
  2. 但反过来,可迭代对象却不一定是一个迭代器,但能通过iter函数实现。
  3. 迭代器可以通过next函数访问下一个值,也可以和可迭代对象一样for循环遍历。
  4. 生成器就是用来创建迭代器的函数,使用yield关键字,返回一个生成器。
  5. 生成器既是一个可迭代对象,也是一个迭代器。
  6. for循环就是迭代器调用next函数依次访问下一个值。

你可能感兴趣的:(小结-Python-可迭代、迭代器和生成器的区别)