Costo de la función len ()


Respuestas:


341

Es O (1) (tiempo constante, no depende de la longitud real del elemento, muy rápido) en cada tipo que ha mencionado, más sety otros como array.array.


17
Gracias por la útil respuesta! ¿Hay algún tipo nativo para el que este no sea el caso?
mvanveen


84

Todos esos objetos siguen su propia longitud. El tiempo para extraer la longitud es pequeño (O (1) en notación big-O) y consiste principalmente en [descripción aproximada, escrita en términos de Python, no en términos de C]: busque "len" en un diccionario y envíelo al función built_in len que buscará el __len__método del objeto y lo llamará ... todo lo que tiene que hacer esreturn self.length


3
Creo que esta es la respuesta más adecuada, ya que da una idea de los detalles de implementación.
AK

¿Por qué no lengthaparece en el diccionario por dir(list)?
ViFI

esto es lo que estaba buscando
Visakh Vijayan

@ViFI Porque es solo un ejemplo. La list.lenghtvariable ilustrada se implementa en C, no en Python.
Kowalski

73

Las siguientes mediciones proporcionan evidencia de que len()es O (1) para estructuras de datos que se utilizan con frecuencia.

Una nota con respecto a timeit: cuando -sse usa el indicador y se pasan dos cadenas a timeitla primera cadena, se ejecuta solo una vez y no se cronometra.

Lista:

$ python -m timeit -s "l = range(10);" "len(l)"
10000000 loops, best of 3: 0.0677 usec per loop

$ python -m timeit -s "l = range(1000000);" "len(l)"
10000000 loops, best of 3: 0.0688 usec per loop

Tupla:

$ python -m timeit -s "t = (1,)*10;" "len(t)"
10000000 loops, best of 3: 0.0712 usec per loop

$ python -m timeit -s "t = (1,)*1000000;" "len(t)"
10000000 loops, best of 3: 0.0699 usec per loop

Cuerda:

$ python -m timeit -s "s = '1'*10;" "len(s)"
10000000 loops, best of 3: 0.0713 usec per loop

$ python -m timeit -s "s = '1'*1000000;" "len(s)"
10000000 loops, best of 3: 0.0686 usec per loop

Diccionario (comprensión del diccionario disponible en 2.7+):

$ python -mtimeit -s"d = {i:j for i,j in enumerate(range(10))};" "len(d)"
10000000 loops, best of 3: 0.0711 usec per loop

$ python -mtimeit -s"d = {i:j for i,j in enumerate(range(1000000))};" "len(d)"
10000000 loops, best of 3: 0.0727 usec per loop

Formación:

$ python -mtimeit -s"import array;a=array.array('i',range(10));" "len(a)"
10000000 loops, best of 3: 0.0682 usec per loop

$ python -mtimeit -s"import array;a=array.array('i',range(1000000));" "len(a)"
10000000 loops, best of 3: 0.0753 usec per loop

Conjunto (conjunto de comprensión disponible en 2.7+):

$ python -mtimeit -s"s = {i for i in range(10)};" "len(s)"
10000000 loops, best of 3: 0.0754 usec per loop

$ python -mtimeit -s"s = {i for i in range(1000000)};" "len(s)"
10000000 loops, best of 3: 0.0713 usec per loop

Deque:

$ python -mtimeit -s"from collections import deque;d=deque(range(10));" "len(d)"
100000000 loops, best of 3: 0.0163 usec per loop

$ python -mtimeit -s"from collections import deque;d=deque(range(1000000));" "len(d)"
100000000 loops, best of 3: 0.0163 usec per loop

1
Este no es un buen punto de referencia a pesar de que muestra lo que ya sabemos. Esto se debe a que el rango (10) y el rango (1000000) no se supone que sea O (1).
Desconocido

3
Esta es, de lejos, la mejor respuesta. Debería agregar una conclusión por si alguien no se da cuenta del tiempo constante.
santiagobasulto

44
Gracias por el comentario. Agregué una nota sobre la complejidad de O (1) len()y también arreglé las medidas para usar correctamente la -sbandera.
mechanical_meat

Es importante tener en cuenta que guardar la longitud en una variable podría ahorrar una cantidad significativa de tiempo de cálculo: python -m timeit -s "l = range(10000);" "len(l); len(l); len(l)"223 nseg por ciclo python -m timeit -s "l = range(100);" "len(l)"66.2 nsec por ciclo
Radostin Stoyanov

16

len es un O (1) porque en su RAM, las listas se almacenan como tablas (series de direcciones contiguas). Para saber cuándo se detiene la mesa, la computadora necesita dos cosas: longitud y punto de inicio. Es por eso que len () es un O (1), la computadora almacena el valor, por lo que solo necesita buscarlo.


3

He estado pensando en len () en Python depende del tamaño de la lista, por lo que siempre almaceno la longitud en una variable si la uso varias veces. Pero hoy durante la depuración, noté el atributo __len__ en el objeto de la lista, por lo que len () solo debe buscarlo, lo que hace que la complejidad sea O (1). Así que busqué en Google si alguien ya lo ha preguntado y me encontré con esta publicación.


Pero __len__es una función, no una variable que representa la longitud de una lista.
Kowalski

@Kowalski sí, len es una función, pero todo lo que hace es que devuelve self.length
AYUSH SENAPATI

Pero tu publicación no dice nada al respecto. Además, ¿cómo sabes que la list.__len__función se ejecuta en tiempo constante? Lo hace, pero no solo porque es una función. Porque se implementó así.
Kowalski
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.