Python:对非空列表的迭代,没有if-clause出现空。为什么?

时间:2009-03-31 23:53:51

标签: python iterator generator leaky-abstraction

如何在非空序列上进行迭代,没有过滤而没有聚合(sum()等),什么都不产生?

考虑一个简单的例子:

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

按预期产生[('a', 97), ('b', 98), ('c', 99)]

现在,只需将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 个答案:

答案 0 :(得分: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

答案 1 :(得分:4)

next()调用会引发StopIteration异常,它会将堆栈冒泡到外部生成器表达式并停止 迭代。

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

上一课,我想:要小心直接拨打next()

答案 2 :(得分:0)

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

我还建议下一个

答案 3 :(得分:0)

>>> seq=['a','b','c']
>>> list((el,4) for el in seq)
[('a',4), ('b',4), ('c',4)]

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