2009-06-17 14 views
41

Stavo scrivendo una funzione Python che sembrava qualcosa di simileQual è la complessità di runtime delle funzioni di elenco Python?

def foo(some_list): 
    for i in range(0, len(some_list)): 
     bar(some_list[i], i) 

in modo che è stato chiamato con

x = [0, 1, 2, 3, ... ] 
foo(x) 

ho dato per scontato che l'accesso indice delle liste era O(1), ma è stato sorpreso di scoprire che per le liste di grandi dimensioni questo è stato significativamente più lento di quanto mi aspettassi.

La mia domanda, allora, è come sono liste di Python sono implementati, e qual è la complessità di esecuzione dei seguenti

  • indicizzazione: list[x]
  • Popping dalla fine: list.pop()
  • Popping dal inizio: list.pop(0)
  • Estendere la lista: list.append(x)

Per crediti extra, splicing o pop arbitrari.

risposta

34

c'è a very detailed table on python wiki che risponde alla tua domanda.

Tuttavia, nell'esempio in particolare, è necessario utilizzare enumerate per ottenere un indice di un iterabile all'interno di un ciclo. in questo modo:

for i, item in enumerate(some_seq): 
    bar(item, i) 
+0

Perdona la mia ignoranza, ma dov'è la complessità per 'pop()' in quella pagina? – Zaz

+2

@Zaz, pop() senza indice è O (1), con indice, ad es. il primo nella lista, è O (n). dal momento che è necessario ottenere l'elemento O (1) e quindi eliminarlo. Quest'ultimo richiede O (n) di tempo per organizzare tutti gli altri elementi della lista. Maggiori informazioni su questo qui: https://www.ics.uci.edu/~pattis/ICS-33/lectures/complexitypython.txt –

7

La risposta è "indefinita". Il linguaggio Python non definisce l'implementazione sottostante. Qui ci sono alcuni link a una mailing list Thread potreste essere interessati a

Inoltre, il modo più Pythonic di scrivere il ciclo sarebbe questo.:

def foo(some_list): 
    for item in some_list: 
     bar(item) 
+0

Oops, sono consapevole che il mio metodo era in qualche modo inferiore a Pythonic. Per il mio ciclo, avevo bisogno dell'elemento e dell'indice. C'è un buon modo per farlo? (Modifica la mia domanda) –

+6

use- per i, item in enumerate (some_lits): ... –

3

Non posso ancora commentare, quindi

se avete bisogno di indice e il valore quindi utilizzare enumerare:

for idx, item in enumerate(range(10, 100, 10)): 
    print idx, item 
6

liste sono infatti O (1) all'indice - sono implementate come un vettore con sovrassegnazione proporzionale, in modo da eseguire quanto ci si aspetterebbe. La probabile ragione per cui hai trovato questo codice più lento del previsto è la chiamata a "range(0, len(some_list))".

range() crea un nuovo elenco delle dimensioni specificate, quindi se some_list ha 1.000.000 articoli, verrà creato un nuovo elenco di milioni di elementi in primo piano. Questo comportamento cambia in python3 (l'intervallo è un iteratore), a cui l'equivalente python2 è xrange, o meglio ancora per il tuo caso, enumerate

Problemi correlati