我在Python中使用了很多生成器,我经常需要从我的生成器中获取一个且只有一个对象,但我不希望它跳过这个对象,只是为了能够查看它(查看)它的键如果它是一个字典,例如)。
import random
def get_generator():
for i in range(0, 10):
d = {'id': i, value: random.random()}
yield d
g = get_generator()
fields = g.the_function_im_looking_for().keys()
print "this generator will offer " + str(len(fields)) + " fields in each item. "\
"I know this information but I still can iterate over it"
for v in g:
print g
请不要在你的答案中解释变通方法(比如测试循环中的第一个元素),我正在寻找一种“干净”的方法来做到这一点。
答案 0 :(得分:4)
在不推进发电机的情况下,无法从发电机获取元件。这就是发电机的工作原理。你可以使用技巧来存储元素以便以后再次使用它(你似乎已经知道了)。您还可以编写一个类,该类提供使用peek
方法包装生成器的行为。但是你必须做所有发电机制外部的工作。当你得到一个元素时,没有任何方法可以使发生器本身不前进。
答案 1 :(得分:3)
我相信这可以使用itertools.tee()来完成: http://docs.python.org/3/library/itertools.html#itertools.tee
但是存储要求可能会变大。
itertools.tee()允许您从一个迭代器创建两个迭代器。
答案 2 :(得分:3)
您可以创建一个包装器生成器,允许您“查看”下一个值:
_sentinel = object()
class PeekingGenerator(object):
def __init__(self, it):
self.it = it
self.peeked = _sentinel
def __iter__(self):
return self
def next(self):
if self.peeked is not _sentinel:
nextval, self.peeked = self.peeked, _sentinel
else:
nextval = next(self.it)
return nextval
def peek(self):
if self.peeked is _sentinel:
self.peeked = next(self.it)
return self.peeked
这允许您使用.peek()
方法查看下一个值;请注意,如果没有下一个要查看的值,则调用.peek()
会引发StopIteration
。
答案 3 :(得分:2)
没有 clean 方法,一般。这与发电机的整个概念相矛盾。
乐观的情况是,当您对生成的项目有一些特定的知识,并且您可以告诉它有多少可能的项目,而不显式枚举它们(例如,范围0-100中的偶数的数量)。在这种情况下,您可以轻松实现具有附加属性的特殊案例类生成器。
但是在一般情况下(即你不知道有关生成项目的任何具体内容)如果你想知道预先有多少项目,那么你必须真正生成所有项目。所以实际上你不需要发电机。
请注意,有些生成器可以是无限的 - 在这种情况下,“生成元素的数量”这个概念根本没有任何意义。