如果循环遍历list / tuple / sequence,则可以使用len(...)
来推断循环执行的次数。但是当循环遍历迭代器时,你不能。
[为清晰起见更新:我正在考虑一次性使用有限迭代器,我想对项目进行计算并同时计算它们。]
我目前使用显式计数器变量,如下例所示:
def some_function(some_argument):
pass
some_iterator = iter("Hello world")
count = 0
for value in some_iterator:
some_function(value)
count += 1
print("Looped %i times" % count)
鉴于"Hello world"
中有11个字符,
这里的预期输出是:
Looped 11 times
我还使用enumerate(...)
考虑了这个较短的替代方案,但我没有发现这一点:
def some_function(some_argument):
pass
some_iterator = iter("Hello world")
count = 0 # Added for special case, see note below
for count, value in enumerate(some_iterator, start=1):
some_function(value)
print("Looped %i times" % count)
[更新以供参考:@mata发现,如果迭代器为空,那么最初编写的第二个示例将失败。插入count = 0
解决了这个问题,或者我们可以使用for ... else ...
结构来处理此案例。]
它不使用循环中enumerate(...)
的索引,而是将变量设置为循环计数几乎是一个副作用。对我来说这是非常不清楚的,所以我更喜欢第一个带有显式增量的版本。
是否有可接受的Pythonic方法(理想情况下是Python 3和Python 2代码)?
答案 0 :(得分:5)
如果循环没有通过添加一行来运行,您可以将enumerate
的便利性与定义的计数器结合起来:
count = 0 # Counter is set in any case.
for count, item in enumerate(data, start=1):
doSomethingTo(item)
print "Did it %d times" % count
如果只需要计算迭代器中的项目数,而不对项目做任何事情,并且没有列出它们,那么你可以简单地做到:
count = sum(1 for ignored_item in data) # count a 1 for each item
答案 1 :(得分:2)
你可以做各种各样的事情来计算发电机中的物品数量,但无论如何,原来的发电机都会被浪费掉。精确地说,精疲力竭。
length = sum(1 for x in gen)
length = max(c for c, _ in enumerate(gen, 1))
length = len(list(gen))
gen
提供的数据太大,此代码可能会浪费大量内存,但它很容易理解,因此没有人会不得不认真思考墙试图了解这意味着什么。 所有这些仅适用于有限生成器。
如果你想计算长度'迭代器在循环它时,你可以这样做:
length = 0
for length, data in enumerate(gen, 1):
# do stuff
现在,length
将等于生成器生成的元素数量。请注意,您不必手动增加length
,因为length
和data
在循环执行后仍然可用且有效。
编辑:如果你想为每个值执行一些函数并忽略它的返回值(你可以通过使用列表作为函数的参数之一来处理它),你可以试试这个:
length = sum(1 | bool(function(x)) for x in gen)
这将计算将function
应用于生成器的每个元素时的长度。尽管如此,使用enumerate
看起来更好。
答案 2 :(得分:1)
无法获取迭代器中的项目数。想想这个案例
def gen():
a = 1
while True:
yield a
a += 1
f = gen()
for value in f:
# do something
这个迭代器的大小是多少?迭代器结束时,如果,它会引发StopIteration
。相反,当您遍历序列时,序列已经存在,因此可以知道其长度。
你使用的两种方法都很好。 best 取决于您的口味。另一种选择是使用
from itertools import count
for item, counter in zip(iterator, count()):
# do stuff
但是,我认为在大多数情况下,您的第一种传统方法会更清晰。
答案 3 :(得分:0)
这有什么问题?
len(list(some_iterator))