5

sum()没有过滤和聚合(等)的非空序列上的迭代器如何不产生任何结果?

考虑一个简单的例子:

sequence = ['a', 'b', 'c']
list((el, ord(el)) for el in sequence)

[('a', 97), ('b', 98), ('c', 99)]符合预期。

现在,只需将 out 替换为ord(el)从某个生成器中取出第一个值的表达式,使用(...).next()- 请原谅人为的示例:

def odd_integers_up_to_length(str):
    return (x for x in xrange(len(str)) if x%2==1)

list((el, odd_integers_up_to_length(el).next()) for el in sequence)

这产生[]. 是的,空列表。没有('a',东西)元组。没有。

但我们没有过滤、聚合或减少。n没有过滤或聚合的对象生成器表达式必须产生n对象,对吗?这是怎么回事?

4

4 回答 4

13

odd_integers_up_to_length(el).next()将引发 StopIteration,它没有被捕获,但被捕获用于其中的生成器表达式,停止它而不产生任何东西。

查看第一次迭代,当值为“a”时:

>>> odd_integers_up_to_length('a').next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
于 2009-03-31T23:59:40.083 回答
4

发生的情况是next()调用引发了一个StopIteration异常,该异常使堆栈冒泡到外部生成器表达式并停止迭代。

AStopIteration是迭代器发出完成信号的正常方式。通常我们看不到它,因为通常next()调用发生在使用迭代器的构造中,例如for x in iteratoror sum(iterator)。但是当我们next()直接调用时,我们是负责捕捉StopIteration. 不这样做会在抽象中引发泄漏,这会导致外部迭代中出现意外行为。

我想,教训是:小心直接调用next().

于 2009-04-01T00:01:30.220 回答
0

str 是一个保留的关键字,你应该以不同的方式命名你的变量

我也建议下一个

于 2009-04-01T00:03:10.497 回答
0
>>> seq=['a','b','c']
>>> list((el,4) for el in seq)
[('a',4), ('b',4), ('c',4)]

所以这里不会list给你带来麻烦...

于 2009-04-01T00:04:53.097 回答