生成器表达式与yield:为什么'next()'不起作用?

7

我知道一定是我漏看了什么简单的东西。

如果我有这样一个生成器表达式:

>>> serializer=(sn for sn in xrange(0,sys.maxint))

我可以轻松地生成单独的整数,就像这样:

>>> serializer.next()
0
>>> serializer.next()
1
>>> serializer.next()
2

如果我写下这样的生成器:

>>> def ser():
...    for sn in xrange(0,100000):
...       yield sn

这不好:

>>> ser().next()
0
>>> ser().next()
0
>>> ser().next()
0

我错过的是什么?

3个回答

21

ser() 会创建一个生成器。每次调用 ser() 都会返回一个新的生成器实例。你需要像使用表达式一样使用它:

serializer = ser()
serializer.next()

如果不是这样,你只能使用ser()函数一次,并且无法重置它。 此外,你可以更改ser函数以接受最大整数,并使程序更灵活。

def ser(n=sys.maxint):
    for sn in xrange(0, n):
        yield sn

2
没有问题。这绝对不是显而易见的,因为执行此操作的另一种主要函数类型(装饰器)在其中有一个明确的 return wrapper,我猜这是由 yield 语句隐含/自动创建的 :P - Jeff Tratner

5
在您的第二个示例中,您不断创建新实例,并从头开始使用生成器。
g = ser()
g.next()
g.next()

创建生成器一次,多次重复使用。

4
ser()

每次都会初始化一个新的生成器。

要解决这个问题,可以像这样做:

s = ser()
next(s) # next is preferred over .next which is why .next has been removed in Py3
next(s)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接