In primo luogo, non si è misurata la velocità di len()
, voi hanno misurato la velocità di creazione di un elenco/set insieme la velocità di len()
.
Utilizzare la --setup
argomento timeit
:
$ python -m timeit --setup "a=[1,2,3,4,5,6,7,8,9,10]" "len(a)"
10000000 loops, best of 3: 0.0369 usec per loop
$ python -m timeit --setup "a={1,2,3,4,5,6,7,8,9,10}" "len(a)"
10000000 loops, best of 3: 0.0372 usec per loop
Le dichiarazioni si passa a --setup
è gestita prima di misurare la velocità di len()
.
In secondo luogo, si dovrebbe notare che len(a)
è un'affermazione piuttosto veloce. Il processo di misurazione della sua velocità può essere soggetto a "rumore". Si consideri che the code executed (and measured) by timeit è equivalente alla seguente:
for i in itertools.repeat(None, number):
len(a)
Poiché sia len(a)
e itertools.repeat(...).__next__()
sono operazioni rapide e loro velocità possono essere simili, la velocità di itertools.repeat(...).__next__()
può influenzare i tempi.
Per questo motivo, è meglio che misura len(a); len(a); ...; len(a)
(ripetuto 100 volte o giù di lì) in modo che il corpo del ciclo for prende una considerevolmente maggiore quantità di tempo rispetto alla iteratore:
$ python -m timeit --setup "a=[1,2,3,4,5,6,7,8,9,10]" "$(for i in {0..1000}; do echo "len(a)"; done)"
10000 loops, best of 3: 29.2 usec per loop
$ python -m timeit --setup "a={1,2,3,4,5,6,7,8,9,10}" "$(for i in {0..1000}; do echo "len(a)"; done)"
10000 loops, best of 3: 29.3 usec per loop
(I risultati ancora dice che len()
ha le stesse prestazioni su liste e gruppi, ma ora si è certi che il risultato è corretto.)
in terzo luogo, è vero che "complessità" e "velocità" sono correlati, ma ti credo stanno facendo un po 'di confusione Il fatto che len()
abbia la complessità O (1) per elenchi e insiemi non implica che debba essere eseguito con la stessa velocità su elenchi e insiemi.
Significa che, in media, indipendentemente dalla lunghezza dell'elenco a
, len(a)
esegue lo stesso numero asintotico di passaggi. E non importa quanto sia lungo il set b
, len(b)
esegue lo stesso numero asintotico di passaggi. Ma l'algoritmo per calcolare la dimensione di liste e insiemi può essere diverso, con conseguenti prestazioni diverse (timeit indica che non è questo il caso, tuttavia questa potrebbe essere una possibilità).
Infine,
Se la creazione di un oggetto di serie richiede più tempo rispetto alla creazione di un elenco, quale sarebbe la ragione di fondo?
Un set, come sapete, non consente elementi ripetuti. Gli insiemi in CPython sono implementati come tabelle hash (per garantire l'inserimento medio e la ricerca O (1)): la costruzione e il mantenimento di una tabella hash è molto più complessa dell'aggiunta di elementi a un elenco.
In particolare, quando si costruisce un set, è necessario calcolare gli hash, compilare la tabella hash, cercarlo per evitare di inserire eventi duplicati e così via. Al contrario, gli elenchi in CPython sono implementati come una semplice matrice di puntatori che è malloc()
ed e realloc()
ed, se necessario.
L'ultima frase probabilmente ha ragione. L'hashing è coinvolto quando si aggiungono elementi a un set. –
Si può provare a cronometrare il blocco senza 'len()' per scoprirlo :) – Caramiriel
@Caramiriel o separare due stringhe e passare l'opzione '-s' :) – Maroun