1. 可迭代對象
from collection import Iterableclass Iterable(metaclass=ABCMeta):...def __iter__(self): # 只實現了__iter__ 方法while False:yield None
能夠在 for ... in obj:中使用的對象(obj)就是一個可迭代對象。
2. 迭代器
from collections import Iteratorclass Iterator(Iterable): # Iterable的子類 ...def __next__(self): # 實現了 __next__raise StopIterationdef __iter__(self): # 也實現了 __iter__return self
能夠使用.next() 或者 .__next__() 方法,在沒有下一個元素時,返回 StopIteration 異常的對象,都是迭代器,可迭代對象轉換成迭代器的方法是: iter(obj) 返回的就是一個迭代器。
>>> a = [] >>> a [] >>> s = iter(a) >>> s <list_iterator object at 0x7feac859b048> >>> s.next() # 這個方法不存在,拋出的是屬性錯誤異常 Traceback (most recent call last):File "<stdin>", line 1, in <module> AttributeError: 'list_iterator' object has no attribute 'next' >>> s.__next__ <method-wrapper '__next__' of list_iterator object at 0x7feac859b048> >>> s.__next__() # 這個方法存在,拋出的是 StopIteration 異常 Traceback (most recent call last):File "<stdin>", line 1, in <module> StopIteration >>>
實現自己的迭代器:
class Reverse:def __init__(self, data):self.data = dataself.index = len(data)def __iter__(self):return selfdef __next__(self): # py2: next()方法if self.index == 0:raise StopIterationself.index = self.index - 1return self.data[self.index]rev = Reverse('timlinux') for char in rev:print(char)
?
3. 生成器yield
生成器(generator)是用來構造迭代器的一種語法工具,通過使用 yield 關鍵字來代替 return,并自動構建好 __iter__() 和 __next__() 兩個方法:
- yield 關鍵字的位置將發生 return 操作
- yield 關鍵字存在的函數中,將具有 __iter__, __next__ 函數
def reverse(data):max_len = len(data) - 1min_len = -1for index in range(max_len, min_len, -1):yield data[index]x = reverse('timlinux') dir(x) # py3: 返回的對象有 __iter__, __next__ 方法# py2: 返回的對象有 __iter__, next 方法
列表生成式中的 [] 換成 (),得到的對象就不再是一個列表,而是一個生成器:
>>> L = [x*x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x*x for x in range(10)) >>> g <generator object <genexpr> at 0x7f9a8dd48a00>
4. 場景
在使用中分配內存,而不是一次分配所有的內存。
?