Python: 是否有可能预先知道迭代器对象中有多少次迭代?

4

到目前为止,如果我想知道迭代器中有多少个迭代次数(在我的情况下,是文件中有多少蛋白质序列),我会这样做:

count = 0
for stuff in iterator:
    count += 1
print count

然而,我想将迭代器分成两半,因此需要知道迭代的总次数。有没有一种方法可以在不遍历迭代器的情况下知道迭代的次数?

5个回答

10

没有办法在不消耗完迭代器的情况下知道它会产生多少值。请注意,迭代器也可以是无限的,因此在这种情况下,总计数甚至没有定义。

如果您可以确保迭代器是有限的,实现您所要求的一种方法是将其转换为列表(使用 list(iterator)),然后使用常规列表函数(len,切片)将其分成两半。当然,在这种方式中,所有项目将同时存在于内存中,这可能或可能不在您的情况下可接受。

或者,您可以尝试使用自定义迭代器类来跟踪即将生成的项目的总数。是否可行取决于获取所述迭代器的确切方式。


我完全同意你的回答,Paolo,你认为我提到停机问题是否相关? - jimifiki

5
自从迭代器协议只定义了两种方法:
iterator.__iter__()

iterator.next()

一般情况下,您无法在迭代器中遍历它们之前知道有限迭代器中项目的数量。


1

我认为Niek de Klein提出的问题与“停机问题”(http://en.wikipedia.org/wiki/Halting_problem)有关。因此,出于强烈的理论原因,无法确定迭代器的长度!

我的意思是,我可以编写一个Python迭代器,以便如果存在这样的成员函数,则我已经解决了停机问题。

当然,特定的容器或您自己的自定义类(如Paolo所建议的)可以具有这样的方法。但是,不能有一般的方法在有限时间内运行!


我认为这个问题与停机问题有着很遥远的关系,即使从技术上讲是正确的。 - Xavier Combelle
我同意计数蛋白质问题更像是“容器中有多少元素”的问题,但我想指出的是,无论迭代器是在特定的东西上(比如列表或字典),还是Niek不应该等待一个通用的len(iterator)比计数器工作得更好的版本发布。而且,使用图灵的结果来激励我的回答,很可爱! - jimifiki

1

你可以使用list()将迭代器转换为列表,然后使用len()获取列表的大小,例如:

len(list(iterator))

7
对于较大的列表而言,这可能会很昂贵。sum(1 for x in iterator) 可能作为一种通用解决方案更好。 - Noufal Ibrahim
@NoufalIbrahim 这是个不错的技巧,很可能是最好的答案,因为蛋白质数据库往往很大(NR 任何人都知道吧?),试图将它们塞进内存并不是最好的想法。 - soulcheck

0

已经提供了四个答案并且有一个被接受了,但是你的问题是否正确呢?如果你有一个蛋白质序列文件,那么迭代器是否是最好的文件接口呢?如果你只需要一个序列数量的初始近似值,那么可以非常廉价地通过文件长度除以平均序列长度来得到,如果事先已知。或者,如果迭代器由数据库支持,记录数可以直接查询。


迭代器来自于 Biopython 这个生物信息学库提供的函数。我不想自己编写迭代器。 - Niek de Klein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接