按照让恩(Jean)对以下问题的回答:Python converting strings in a list to numbers,当运行以下最小代码时,我得到一个StopIteration异常。

primesz2为空。

通过谷歌搜索,我认为我可能需要在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)

09-28 06:09