Mi sono occupato del lavoro con i tipi di raccolta set
e frozenset
di Python.Set vs. prestazioni frozenset
Inizialmente, ho assunto che frozenset
fornirebbe prestazioni di ricerca migliori rispetto a set
, come immutabile e quindi potrebbe sfruttare la struttura degli elementi memorizzati.
Tuttavia, questo non sembra essere il caso, per quanto riguarda il seguente esperimento:
import random
import time
import sys
def main(n):
numbers = []
for _ in xrange(n):
numbers.append(random.randint(0, sys.maxint))
set_ = set(numbers)
frozenset_ = frozenset(set_)
start = time.time()
for number in numbers:
number in set_
set_duration = time.time() - start
start = time.time()
for number in numbers:
number in frozenset_
frozenset_duration = time.time() - start
print "set : %.3f" % set_duration
print "frozenset: %.3f" % frozenset_duration
if __name__ == "__main__":
n = int(sys.argv[1])
main(n)
ho eseguito questo codice utilizzando sia CPython e PyPy, che ha dato i seguenti risultati:
> pypy set.py 100000000
set : 6.156
frozenset: 6.166
> python set.py 100000000
set : 16.824
frozenset: 17.248
Sembra che frozenset
sia effettivamente più lento per quanto riguarda le prestazioni di ricerca, sia in CPython che in PyPy. Qualcuno ha un'idea del perché questo è il caso? Non ho esaminato le implementazioni.
"come è immutabile e quindi potrebbe sfruttare la struttura degli elementi memorizzati "- cosa ti aspettavi esattamente che facesse? Qualsiasi struttura a cui ha accesso, anche 'set' ha. – user2357112
Bene, questo è quello che sto chiedendo. Ho pensato che forse frozenset potesse usare una sorta di funzione di hash precalcolata, che a sua volta poteva fornire migliori prestazioni di ricerca. –
Devi calcolare l'hash di qualsiasi oggetto che cerchi, punto. Non puoi precaricare gli hash qui, poiché puoi testare un oggetto arbitrario contro il set. Non sono sicuro di come immagini questa ottimizzazione? Gli articoli * in * del set non hanno bisogno di avere il loro hash calcolato; sono già stati inseriti nel tavolo degli hash. –