Solo índice necesario: enumerar o (x) rango?

Si quiero usar solo el índice dentro de un bucle, debo usar mejor la función range/xrange en combinación con len()

 a = [1,2,3] for i in xrange(len(a)): print i 

o enumerate ? Incluso si no voy a usar p en absoluto?

 for i,p in enumerate(a): print i 

Yo usaría enumerate porque es más genérico; por ejemplo, funcionará en iterables y secuencias, y la sobrecarga por solo devolver una referencia a un objeto no es tan importante, mientras que xrange(len(something)) aunque (para mí) más fácil de leer según su intención: se romperá en objetos sin soporte para len

Ese es un requisito poco frecuente: la única información que se utiliza en el contenedor es su longitud. En este caso, de hecho, hacer este hecho explícito y utilizar la primera versión.

Usar xrange con len es un caso de uso bastante común, así que sí, puede usarlo si solo necesita acceder a los valores por índice.

Pero si prefiere usar la enumeración por algún motivo, puede usar el guión bajo (_), es solo una notación que se ve con frecuencia y muestra que no usará la variable de alguna manera significativa:

 for i, _ in enumerate(a): print i 

También hay una trampa que puede suceder usando el guión bajo (_). También es común nombrar a las funciones de ‘traducción’ como _ en las bibliotecas y sistemas i18n, así que tenga cuidado de usarlo con gettext o alguna otra biblioteca de este tipo (gracias a @lazyr).

xrange debería ser un poco más rápido, pero enumerar significará que no necesita cambiarlo cuando se da cuenta de que necesita p después de todo

Basado en su código de muestra,

 res = [[profiel.attr[i].x for i,p in enumerate(profiel.attr)] for profiel in prof_obj] 

Yo lo reemplazaria por

 res = [[px for p in profiel.attr] for profiel in prof_obj] 

Escribí esto porque quería probarlo. Así que depende si necesitas los valores con los que trabajar.

Código:

 testlist = [] for i in range(10000): testlist.append(i) def rangelist(): a = 0 for i in range(len(testlist)): a += i a = testlist[i] + 1 # Comment this line for example for testing def enumlist(): b = 0 for i, x in enumerate(testlist): b += i b = x + 1 # Comment this line for example for testing import timeit t = timeit.Timer(lambda: rangelist()) print("range(len()):") print(t.timeit(number=10000)) t = timeit.Timer(lambda: enumlist()) print("enum():") print(t.timeit(number=10000)) 

Ahora puedes ejecutarlo y obtendrás el resultado más probable, que enum () es más rápido. Cuando comenta la fuente en a = testlist[i] + 1 y b = x + 1 verá que el rango (len ()) es más rápido.

Por el código anterior obtengo:

 range(len()): 18.766527627612255 enum(): 15.353173553868345 

Ahora, al comentar como se indicó anteriormente obtengo:

 range(len()): 8.231641875551514 enum(): 9.974262515773656 

Hice una prueba de tiempo y descubrí que el rango es aproximadamente 2 veces más rápido que enumerar. (en Python 3.6 para Win32)

lo mejor de 3, para len (a) = 1M

  • enumerar (a): 0.125s
  • rango (len (a)): 0.058s

Espero eso ayude.

Para tu información: Inicialmente comencé esta prueba para comparar la velocidad de python vs vba … y descubrí que vba es en realidad 7 veces más rápido que el método de rango … ¿es debido a mis pobres habilidades con python?

seguramente python puede hacerlo mejor que vba de alguna manera

guión para enumerar

 import time a = [0] a = a * 1000000 time.perf_counter() for i,j in enumerate(a): pass print(time.perf_counter()) 

guión para rango

 import time a = [0] a = a * 1000000 time.perf_counter() for i in range(len(a)): pass print(time.perf_counter()) 

script para vba (0.008s)

 Sub timetest_for() Dim a(1000000) As Byte Dim i As Long tproc = Timer For i = 1 To UBound(a) Next i Debug.Print Timer - tproc End Sub 

Solo usa el range() . Si va a utilizar todos los índices de todos modos, xrange() no proporciona ningún beneficio real (a menos que len(a) sea ​​realmente grande). Y enumerate() crea una estructura de datos más rica que vas a tirar de inmediato.