【Python基础】迭代器

因学识经验有限,如有不正之处望读者指正,不胜感激;也望借此平台留下学习笔记以温故而知新。这一篇博客是Python基础之迭代器,借此梳理下,希望对您有所帮助。

1、可迭代对象

可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如list,tuple,dict,set,str等
一类是generator ,包括生成器和带yeild的generator function
这些可以 直接作用于for循环的对象统称为可迭代对象:Iterable

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

a = [i for i in range(10)]
next(a)

结果返回:

---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

 in 
      1 a = [i for i in range(10)]
----> 2 next(a)


TypeError: 'list' object is not an iterator

list,dict,str虽然是Iterable,却不是Iterator

from collections import Iterator
from collections import Iterable
print(isinstance(a,Iterator))
print(isinstance(a,Iterable))
print(isinstance({},Iterable))
print(isinstance('abc',Iterable))

结果返回如下:

False
True
True
True

2、iter()函数

iter(iterable)#一个参数,要求参数为可迭代的类型

把list、dict、str等Iterable变成Iterator可以使用iter()函数:

print(isinstance({},Iterator))
print(isinstance('abc',Iterator))
print(isinstance(iter({}),Iterator))
print(isinstance(iter('abc'),Iterator))

结果返回如下:

False
False
True
True

为什么list、dict、str等数据类型不是Iterator?

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

小结

  • 凡是可作用于for循环的对象都是Iterable类型;
  • 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
  • 集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:

x = [1,2,3]
for i in x:
    print(i)

实际情况如下:

【Python基础】迭代器_第1张图片

等价于:

# 首先获得Iterator对象:
iterator = iter([1, 2, 3])
# 循环:
while True:
    try:
        # 获得下一个值:
        x = next(iterator)
        print(x)
    except StopIteration:
        # 遇到StopIteration就退出循环
        break

3、创建迭代器(类)

把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。

如果你已经了解的面向对象编程,就知道类都有一个构造函数,Python 的构造函数为 __init__(), 它会在对象初始化的时候执行

__iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。

from itertools import islice
class Fib:
    def __init__(self):
        self.prev = 0
        self.curr = 1
    def __iter__(self):
        return self
    def __next__(self):
        self.prev,self.curr = self.curr,self.prev+self.curr
        return self.curr
f = Fib()
print(list(islice(f ,0,10)))

结果如下:

[1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

Fib既是一个可迭代对象(因为它实现了 __iter__方法),又是一个迭代器(因为实现了 __next__方法)

4、讨论

如何判断是可迭代对象还是迭代器?如何把可迭代对象转换为迭代器?

from collections import Iterator  # 迭代器
from collections import Iterable  # 可迭代对象

s = 'hello'

print(isinstance(s, Iterator))  # 判断是不是迭代器
print(isinstance(s, Iterable))  # 判断是不是可迭代对象

print(isinstance(iter(s), Iterator))  # 把可迭代对象转换为迭代器 iter(s)

参考资料

博客:https://blog.csdn.net/sunchengquan/article/details/84494101

博客:https://blog.csdn.net/sumatch/article/details/99072268

你可能感兴趣的:(Python)