Ответ 1
Вы можете попробовать itertools.islice(iterable[, start], stop[, step])
:
import itertools
for line in itertools.islice(list , start, stop):
foo(line)
Я хочу перебрать все в списке, кроме первых нескольких элементов, например:
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
представляется оптимальным решением для этой проблемы, так или иначе, дополнительный импорт просто кажется излишним для чего-то настолько простого.
Лично я нахожу решение enumerate
прекрасно читаемым и сжатым - хотя я бы предпочел написать его вот так:
for index, line in enumerate(lines):
if index >= 2:
foo(line)
Исходное решение в большинстве случаев является подходящим.
for line in lines[2:]:
foo(line)
Пока это копирует список, это только мелкая копия, и довольно быстро. Не беспокойтесь об оптимизации, пока вы не профилировали код и не обнаружили это узким местом.
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 ):
не беспокоиться.
Вы можете создать вспомогательный генератор:
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)
for fooable in (line for i,line in enumerate(lines) if i >= 2):
foo(fooable)
Я предпочитаю использовать dropwhile. Он чувствует себя естественно после использования его в Haskell и некоторых других языках и кажется достаточно понятным. Вы также можете использовать его во многих других случаях, когда вы хотите найти более сложное условие триггера, чем индекс элемента для начала итерации.
from itertools import dropwhile
for item in dropwhile(lambda x: x[0] < 2, enumerate(lst)):
# ... do something with item