# generator
def even_gen():
result = 0
while True:
yield result
result += 2
# generator expression
def even_genexp():
return (num for num in even_gen()) # or even_iter or even_getitem
# not much value under these circumstances
# iterator protocol
class even_iter():
def __init__(self):
self.value = 0
def __iter__(self):
return self
def __next__(self):
next_value = self.value
self.value += 2
return next_value
# getitem method
class even_getitem():
def __getitem__(self, index):
return index * 2
import random
for iterator in even_gen, even_genexp, even_iter, even_getitem:
limit = random.randint(15, 30)
count = 0
for even in iterator():
print even,
count += 1
if count >= limit:
break
print
首先,itertools module对于迭代器可能很有用的各种情况都非常有用,但这里是用python创建迭代器所需的全部:
很酷吧?收益率可以用来代替函数中的正常收益率。它返回的对象是相同的,但它不是销毁状态并退出,而是保存状态,以便在您希望执行下一次迭代时使用。下面是一个直接从itertools function list中提取的操作示例:
如函数描述中所述(这是itertools模块中的count()函数…),它生成一个迭代器,返回以n开头的连续整数
Generator expressions是另一种蠕虫(可怕的蠕虫!)。它们可以用来代替List Comprehension来节省内存(列表理解在内存中创建一个列表,如果没有分配给变量,则在使用后会被销毁,但是生成器表达式可以创建生成器对象。。。这是迭代器的一种奇特说法。以下是生成器表达式定义的示例:
这与上面的迭代器定义非常相似,只是整个范围预定在0到10之间。
我刚刚找到了xrange()(我以前没见过它…)并将其添加到上面的示例中。xrange()是range()的一个可重用版本,它的优点是不预先构建列表。如果你有一个庞大的数据体来迭代,并且只有这么多的内存来完成它,这将是非常有用的。
有四种方法可以构建迭代函数:
next
)示例:
要查看所有四种方法的运行情况:
结果是:
注意:
两种生成器类型(
uc_gen
和uc_genexp
)不能是reversed()
;普通迭代器(uc_iter
)需要__reversed__
magic方法(必须返回一个新的向后的迭代器);getitem可迭代(uc_getitem
)必须具有__len__
magic方法:为了回答Panic上校关于无限延迟评估迭代器的第二个问题,下面是这些例子,使用上面四种方法中的每一种:
结果(至少对于我的样本运行而言):
如何选择使用哪一个?这主要是口味的问题。我经常看到的两个方法是生成器和迭代器协议,以及一个混合的(
__iter__
返回生成器)。生成器表达式对于替换列表理解非常有用(它们很懒,因此可以节省资源)。
如果需要与早期Python 2.x版本兼容,请使用
__getitem__
。python中的迭代器对象符合迭代器协议,这基本上意味着它们提供了两种方法:
__iter__()
和__next__()
。__iter__
返回迭代器对象并隐式调用 在循环开始时。__next__()
方法返回下一个值,并在每个循环增量处隐式调用。当没有更多的值可返回时,此方法引发StopIteration异常,循环构造将隐式捕获该异常以停止迭代。下面是一个简单的计数器示例:
这将打印:
如前一个答案所述,使用生成器更容易编写:
打印输出将相同。在引擎盖下,生成器对象支持迭代器协议,并执行与类计数器大致相似的操作。
David Mertz的文章Iterators and Simple Generators是一个很好的介绍。
相关问题 更多 >
编程相关推荐