pythonic的方式迭代列表的一部分

我想遍历列表中除前几个元素外的所有内容,例如:

for line in lines[2:]: foo(line) 

这是简洁的,但复制整个列表,这是不必要的。 我可以:

 del lines[0:2] for line in lines: foo(line) 

但是这个修改列表,这并不总是好的。

我可以做这个:

 for i in xrange(2, len(lines)): line = lines[i] foo(line) 

但是,这只是毛病。

更好的可能是这样的:

 for i,line in enumerate(lines): if i < 2: continue foo(line) 

但这并不像第一个例子那么明显。

所以:做什么的方法与第一个例子一样明显,但不会不必要地复制列表?

你可以尝试itertools.islice(iterable[, start], stop[, step])

 import itertools for line in itertools.islice(list , start, stop): foo(line) 

虽然itertools.islice似乎是这个问题的最佳解决scheme,不知何故,额外的导入似乎是如此简单的东西矫枉过正。

就个人而言,我发现enumerate解决scheme完全可读和简洁 – 虽然我宁愿写这样的:

 for index, line in enumerate(lines): if index >= 2: foo(line) 

在大多数情况下,最初的解决scheme是适当的解决scheme。

 for line in lines[2:]: foo(line) 

虽然这样做复制列表,它只是一个浅的副本,并且相当快。 不要担心优化,直到你已经分析了代码,发现这是一个瓶颈。

 for fooable in (line for i,line in enumerate(lines) if i >= 2): foo(fooable) 

我更喜欢用这个。 在Haskell和其他一些语言中使用它后感觉很自然,看起来很合理。 您还可以在许多其他情况下使用它,在这种情况下,您希望查找比迭代开始时的项目索引更复杂的“触发”条件。

 from itertools import dropwhile for item in dropwhile(lambda x: x[0] < 2, enumerate(lst)): # ... do something with item 

你可以build立一个辅助生成器:

 def rangeit(lst, rng): for i in rng: yield lst[i] for e in rangeit(["A","B","C","D","E","F"], range(2,4)): print(e) 
 def skip_heading( iterable, items ): the_iter= iter( iterable ): for i, e in enumerate(the_iter): if i == items: break for e in the_iter: yield e 

现在你可以for i in skip_heading( lines, 2 ):无需担心。