按照让恩(Jean)对以下问题的回答:Python converting strings in a list to numbers,当运行以下最小代码时,我得到一个StopIteration
异常。primes
和z2
为空。
通过谷歌搜索,我认为我可能需要在traceback中绕行一会儿,但是我不确定该如何解决?
追溯:
File "factorise_v32.py", line 118, in factorise
primes=[next(z2) for _ in xrange(b)]
StopIteration
CSV文件中的样本数据:
("2","3","5","7","11")
最小代码:
import csv
def factorise(N)
....
z1=(int(x) for row in csv.reader(csvfile) for x in row)
....
b=4 #b can be any positive integer
z2=(int(x) for row in csv.reader(csvfile) for x in row)
primes=[next(z2) for _ in xrange(b)]
最佳答案
列表推导本身不是生成器或迭代器。当表达式端引发StopIteration
异常时,它不会停止。 for ... in <iterable>
循环的可迭代过程可以使用StopIteration
来与for
循环进行通信,说明迭代已完成,但是并没有扩展到构造的其余部分。
如果您需要从迭代器获取最多b
个元素,请使用itertools.islice()
:
primes = list(islice(z2, b))
迭代时最多占用
b
个元素,如果z2
中没有足够的元素,则较少。您链接到的帖子的早期版本尝试通过为
0
设置默认值,以b
值填充结果,以防元素少于next()
。我会使用itertools.repeat()
和itertools.chain()
来实现这一点:primes = list(islice(chain(z2, repeat(0)), b))
chain(z2, repeat(0))
用尽后,0
部分将不断添加z2
值。 islice()
从该序列中获取b
个元素。演示:
>>> from itertools import chain, repeat, islice
>>> z2 = iter([1, 2, 3])
>>> list(islice(z2, 5)) # up to 5
[1, 2, 3]
>>> z2 = iter([1, 2, 3]) # pad with zeros
>>> list(islice(chain(z2, repeat(0)), 5))
[1, 2, 3, 0, 0]
请注意,您不能连续两次从CSV文件中读取内容,而且必须先回退文件对象。您的代码在两个位置使用
csv.reader(csvfile)
,但是csvfile
文件对象不会返回到开始。在尝试再次读取之前,添加csvfile.seek(0)
。