forma pythonica de iterar sobre parte de una lista

Quiero recorrer todo en una lista, excepto los primeros elementos, por ejemplo:

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

Esto es conciso, pero copia la lista completa, lo cual es innecesario. Yo podría hacer:

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

Pero esto modifica la lista, lo que no siempre es bueno.

Puedo hacer esto:

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

Pero, eso es simplemente asqueroso.

Mejor podría ser esto:

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

Pero no es tan obvio como el primer ejemplo.

Entonces: ¿Cuál es una forma de hacerlo que es tan obvia como el primer ejemplo, pero no copia la lista innecesariamente?

Puede probar itertools.islice(iterable[, start], stop[, step]) :

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

Aunque itertools.islice parece ser la solución óptima para este problema, de alguna manera, la importación adicional parece una exageración para algo tan simple.

Personalmente, encuentro la solución enumerate perfectamente legible y sucinta, aunque preferiría escribirla así:

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

La solución original es, en la mayoría de los casos, la adecuada.

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

Si bien esto copia la lista, es solo una copia superficial y es bastante rápido. No se preocupe por la optimización hasta que haya perfilado el código y haya encontrado que se trata de un cuello de botella.

Usted podría construir un generador de ayuda:

 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 

Ahora puedes for i in skip_heading( lines, 2 ): sin preocuparte.

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

Prefiero usar Dropwhile para esto. Se siente natural después de usarlo en Haskell y en otros idiomas, y parece razonablemente claro. También puede usarlo en muchos otros casos en los que desea buscar una condición “desencadenante” más compleja que el índice del elemento para el inicio de la iteración.

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