[英]Python: an iteration over a non-empty list with no if-clause comes up empty. Why?
没有过滤和聚合( 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',
stuff )
元组。 没有什么。
但我们没有过滤、聚合或减少。 没有过滤或聚合的n
对象的生成器表达式必须产生n
对象,对吗? 这是怎么回事?
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
发生的情况是next()
调用引发了一个StopIteration
异常,该异常使堆栈冒泡到外部生成器表达式并停止该迭代。
StopIteration
是迭代器发出完成信号的正常方式。 通常我们看不到它,因为通常next()
调用发生在使用迭代器的构造中,例如for x in iterator
或sum(iterator)
。 但是当我们直接调用next()
时,我们是负责捕获StopIteration
的人。 不这样做会在抽象中引发泄漏,这会导致外部迭代中出现意外行为。
我想,教训是:小心直接调用next()
。
str 是一个保留的关键字,你应该以不同的方式命名你的变量
我也建议下一个
>>> seq=['a','b','c']
>>> list((el,4) for el in seq)
[('a',4), ('b',4), ('c',4)]
所以这里不是给你带来麻烦的list
......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.