# 迭代器 iter()函数与next()函数 for...in...循环的本质

## 1. 可迭代对象

>>> for i in 100:
...     print(i)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>>
# int整型不是iterable，即int整型不是可以迭代的

>>> class MyList(object):
...     def __init__(self):
...             self.container = []
...             self.container.append(item)
...
>>> mylist = MyList()
>>> for num in mylist:
...     print(num)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'MyList' object is not iterable
>>>
# MyList容器的对象也是不能迭代的


## 2. 如何判断一个对象是否可以迭代

In [50]: from collections import Iterable

In [51]: isinstance([], Iterable)
Out[51]: True

In [52]: isinstance({}, Iterable)
Out[52]: True

In [53]: isinstance('abc', Iterable)
Out[53]: True

In [54]: isinstance(mylist, Iterable)
Out[54]: False

In [55]: isinstance(100, Iterable)
Out[55]: False


## 3. 可迭代对象的本质

>>> class MyList(object):
...     def __init__(self):
...             self.container = []
...             self.container.append(item)
...     def __iter__(self):
...             """返回一个迭代器"""
...             # 我们暂时忽略如何构造一个迭代器对象
...             pass
...
>>> mylist = MyList()
>>> from collections import Iterable
>>> isinstance(mylist, Iterable)
True
>>>
# 这回测试发现添加了__iter__方法的mylist对象已经是一个可迭代对象了


## 4. iter()函数与next()函数

list、tuple等都是可迭代对象，我们可以通过iter()函数获取这些可迭代对象的迭代器。然后我们可以对获取到的迭代器不断使用next()函数来获取下一条数据。iter()函数实际上就是调用了可迭代对象的__iter__方法。

>>> li = [11, 22, 33, 44, 55]
>>> li_iter = iter(li)
>>> next(li_iter)
11
>>> next(li_iter)
22
>>> next(li_iter)
33
>>> next(li_iter)
44
>>> next(li_iter)
55
>>> next(li_iter)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>


## 5. 如何判断一个对象是否是迭代器

In [56]: from collections import Iterator

In [57]: isinstance([], Iterator)
Out[57]: False

In [58]: isinstance(iter([]), Iterator)
Out[58]: True

In [59]: isinstance(iter("abc"), Iterator)
Out[59]: True


## *6. 迭代器Iterator

class MyList(object):
"""自定义的一个可迭代对象"""
def __init__(self):
self.items = []

self.items.append(val)

def __iter__(self):
myiterator = MyIterator(self)
return myiterator

class MyIterator(object):
"""自定义的供上面可迭代对象使用的一个迭代器"""
def __init__(self, mylist):
self.mylist = mylist
# current用来记录当前访问到的位置
self.current = 0

def __next__(self):
if self.current < len(self.mylist.items):
item = self.mylist.items[self.current]
self.current += 1
return item
else:
raise StopIteration

def __iter__(self):
return self

if __name__ == '__main__':
mylist = MyList()
for num in mylist:
print(num)


## *7. for…in…循环的本质

for item in Iterable 循环的本质就是先通过iter()函数获取可迭代对象Iterable的迭代器，然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item，当遇到StopIteration的异常后循环结束。

## 8. 迭代器的应用场景

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …

class FibIterator(object):
"""斐波那契数列迭代器"""
def __init__(self, n):
"""
:param n: int, 指明生成数列的前n个数
"""
self.n = n
# current用来保存当前生成到数列中的第几个数了
self.current = 0
# num1用来保存前前一个数，初始值为数列中的第一个数0
self.num1 = 0
# num2用来保存前一个数，初始值为数列中的第二个数1
self.num2 = 1

def __next__(self):
"""被next()函数调用来获取下一个数"""
if self.current < self.n:
num = self.num1
self.num1, self.num2 = self.num2, self.num1+self.num2
self.current += 1
return num
else:
raise StopIteration

def __iter__(self):
"""迭代器的__iter__返回自身即可"""
return self

if __name__ == '__main__':
fib = FibIterator(10)
for num in fib:
print(num, end=" ")


## 9. 并不是只有for循环能接收可迭代对象

li = list(FibIterator(15))
print(li)
tp = tuple(FibIterator(6))
print(tp)


©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客