[TimLinux] Python 迭代器(iterator)和生成器(generator)

1. 可迭代对象

from collection import Iterable

class Iterable(metaclass=ABCMeta):
...
def __iter__(self): # 只实现了__iter__ 方法
while False:
yield None

能够在 for ... in obj:中使用的对象(obj)就是一个可迭代对象。

2. 迭代器

from collections import Iterator

class Iterator(Iterable):  # Iterable的子类
...
def __next__(self): # 实现了 __next__
raise StopIteration def __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 = data
self.index = len(data) def __iter__(self):
return self def __next__(self): # py2: next()方法
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return 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) - 1
min_len = -1
for 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. 场景

在使用中分配内存,而不是一次分配所有的内存。

上一篇:JavaScript中点号“.”的多义性


下一篇:ES6中的迭代器、Generator函数以及Generator函数的异步操作