Costo della funzione len ()


Risposte:


341

È O (1) (tempo costante, non dipendente dalla lunghezza effettiva dell'elemento - molto veloce) su ogni tipo che hai citato, più sete altri come array.array.


17
Grazie per la risposta utile! Esistono tipi nativi per i quali non è così?
mvanveen,


84

Tutti quegli oggetti tengono traccia della loro lunghezza. Il tempo per estrarre la lunghezza è piccolo (O (1) nella notazione big-O) e consiste principalmente di [descrizione approssimativa, scritta in termini Python, non in termini C]: cercare "len" in un dizionario e inviarlo al built_in len che cerca il __len__metodo dell'oggetto e lo chiama ... tutto quello che deve fare èreturn self.length


3
Penso che questa sia la risposta più appropriata in quanto fornisce informazioni dettagliate sui dettagli di implementazione.
AK,

perché non lengthappare nel dizionario di dir(list)?
ViFI,

questo è quello che stavo cercando
Visakh Vijayan,

@ViFI Perché è solo un esempio. La list.lenghtvariabile illustrata è implementata in C, non in Python.
Kowalski,

73

Le misurazioni seguenti forniscono prove che len()è O (1) per le strutture di dati spesso utilizzate.

Una nota relativa a timeit: Quando -sviene utilizzato il flag e due stringhe vengono passate alla timeitprima stringa viene eseguita una sola volta e non è temporizzata.

Elenco:

$ 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

tuple:

$ 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

Corda:

$ 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

Dizionario (comprensione del dizionario disponibile in 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

Vettore:

$ 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

Set (set-comprensione disponibile in 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
Questo non è un buon punto di riferimento anche se mostra ciò che già sappiamo. Questo perché range (10) e range (1000000) non dovrebbero essere O (1).
Sconosciuto il

3
Questa è di gran lunga la risposta migliore. Dovresti semplicemente aggiungere una conclusione nel caso in cui qualcuno non realizzi il tempo costante.
santiagobasulto,

4
Grazie per il commento. Ho aggiunto una nota sulla complessità O (1) di len(), e ho anche corretto le misure per usare correttamente la -sbandiera.
Mechanical_meat

È importante notare che il salvataggio della lunghezza in una variabile potrebbe far risparmiare una notevole quantità di tempo di calcolo: python -m timeit -s "l = range(10000);" "len(l); len(l); len(l)"223 nsec per loop python -m timeit -s "l = range(100);" "len(l)"66,2 nsec per loop
Radostin Stoyanov

16

len è un O (1) perché nella tua RAM, gli elenchi sono memorizzati come tabelle (serie di indirizzi contigui). Per sapere quando la tabella si ferma, il computer ha bisogno di due cose: lunghezza e punto iniziale. Ecco perché len () è una O (1), il computer memorizza il valore, quindi deve solo cercarlo.


3

Ho pensato a len () in Python dipende dalla dimensione della lista, quindi conservo sempre la lunghezza in una variabile se uso più volte. Ma oggi durante il debug, ho notato l'attributo __len__ nell'oggetto elenco, quindi len () deve semplicemente recuperarlo, il che rende la complessità O (1). Quindi ho solo cercato su Google se qualcuno lo avesse già chiesto e si fosse imbattuto in questo post.


Ma __len__è una funzione, non una variabile che rappresenta la lunghezza di un elenco.
Kowalski,

@Kowalski sì, len è una funzione ma tutto ciò che fa è, restituisce autonomia
AYUSH SENAPATI

Ma il tuo post non dice nulla al riguardo. Inoltre, come fai a sapere che la list.__len__funzione viene eseguita a tempo costante? Lo fa, ma non solo per questo è una funzione. Perché implementato così.
Kowalski,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.