python-多任务编程03-迭代器(iterator)
迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
可迭代对象(Iterable)
能够被循环遍历(迭代)的对象称为可迭代对象,如list、tuple、dict、set、str等。使用以下语句判断是否是可迭代对象
>>> from collections.abc import Iterable >>> isinstance([], Iterable) True >>> isinstance({}, Iterable) True >>> isinstance('abc', Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False
从代码层面上来说,当class中实现了__iter__方法,则该类创建的对象即为可迭代对象
>>> class MyList(object): ... def __init__(self): ... self.container = [] ... def add(self, item): ... self.container.append(item) ... def __iter__(self): ... """返回一个迭代器""" ... # 我们暂时忽略如何构造一个迭代器对象 ... pass ... >>> mylist = MyList() >>> from collections import Iterable >>> isinstance(mylist, Iterable) True >>> # 这回测试发现添加了__iter__方法的mylist对象已经是一个可迭代对象了
可迭代对象的本质
可迭代对象的本质就是可以提供一个迭代器,该迭代器能记录每次访问到了第几条数据,以便每次迭代都可以返回下一条数据。
迭代器(Iterator)
要使得可迭代对象能够正常的循环迭代,必须实现__iter__
方法返回一个迭代器。我们在迭代一个可迭代对象的时候,实际上就是先获取该对象提供的一个迭代器,然后通过这个迭代器来依次获取对象中的每一个数据。
要自定义一个迭代器,必须实现__iter__方法和__next__方法。例:
from collections.abc import Iterable import time class MyList(object): """自定义一个可迭代对象""" def __init__(self): self.content = list() def add(self, item): self.content.append(item) def __iter__(self): # 1.要使一个对象是可迭代对象,必须实现__iter__方法 # 2.要使一个对象迭代时能每次都返回一个值,必须让__iter__返回一个迭代器对象 # 创建迭代器对象 myiterator = MyIterator(self) return myiterator class MyIterator(object): """自定义一个迭代器,必须实现__iter__方法和__next__方法""" def __init__(self, mylist_obj): self.mylist = mylist_obj self.current = 0 def __iter__(self): pass def __next__(self): """每次迭代时返回的值实际是通过__next__方法返回的""" # 1.定义一个下标current,每次调用时+1,用来实现每次调用__next__时,返回下一个值 # 2.注意判断下标current自增时是否会越界,若越界则手动抛出StopIteration异常 # 外层for循环迭代时,若遇到StopIteration异常,则会停止迭代 if self.current == len(self.mylist.content): raise StopIteration value = self.mylist.content[self.current] self.current += 1 return value def main(): my_list = MyList() my_list.add(11) my_list.add(22) my_list.add(33) print('my_list是不是可迭代对象:', isinstance(my_list, Iterable)) my_list_iterator = iter(my_list) print('my_list返回的迭代器为:', my_list_iterator) print('my_list的下一个值为:', next(my_list_iterator)) for i in my_list: print(i) time.sleep(1) if __name__ == '__main__': main()
运行结果为:
上述代码定义了两个类,共同实现一个可迭代对象,我们可以将第二个迭代器类中使用到的方法放到第一个可迭代对象中,这样第一个可迭代对象同时也是一个迭代器。__iter__方法返回的就是自己self,如:
import time class MyList(object): """自定义迭代器""" def __init__(self): self.content = list() self.current = 0 def add(self, value): self.content.append(value) def __iter__(self): return self def __next__(self): # 若越界则抛出StopIteration异常 if self.current == len(self.content): raise StopIteration # 不越界则返回当前迭代的值,并自增下标current value = self.content[self.current] self.current += 1 return value def main(): # 创建迭代器对象 my_list = MyList()
print('my_list是不是一个可迭代对象', isinstance(my_list, Iterable))
print('my_list是不是一个迭代器', isinstance(my_list, Iterator))
# 添加值 my_list.add('小明') my_list.add('小红') my_list.add('小花') # 遍历my_list for value in my_list: print(value) time.sleep(0.5) if __name__ == '__main__': main()
运行结果为:
迭代器实现斐波那契数列
import time class Fibonacci(object): def __init__(self, num): self.a = 0 self.b = 1 self.num = num self.current = 0 def __iter__(self): return self def __next__(self): if self.current == self.num: raise StopIteration temp = self.a self.a, self.b = self.b, self.a + self.b self.current += 1 return temp def main(): fibonacci_1 = Fibonacci(10) fibonacci_2 = Fibonacci(5) fibonacci_3 = Fibonacci(8) # for循环接收可迭代对象 for i in fibonacci_1: print(i) time.sleep(0.2) # list接收可迭代对象 lst = list(fibonacci_2) print(lst) # tuple接收可迭代对象 tpl = tuple(fibonacci_3) print(tpl) if __name__ == '__main__': main()
运行结果为: