如何在非空序列上进行迭代,没有过滤而没有聚合(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
个对象,对吗?发生了什么事?
答案 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 iterator
或sum(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
在这里给你带来麻烦......