Range vs Generator : uso della memoria

g
gullisa (1170 points)
7 24 31
asked Oct 28, 2020 in Programmare in Python by gullisa (1,170 points)
edited Oct 28, 2020 by gullisa
Buonasera,

in termini di uso della memoria per quale ragione l'oggetto range occupa meno memoria dell'equivalente oggetto generatore per un medesimo insieme di valori da memorizzare? Ad es. (Dal mio Spyder):

interval = range(1000)

sys.getsizeof(interval)
Out[56]: 48

inter = list(interval)

sys.getsizeof(inter)
Out[58]: 9112

type(interval)
Out[59]: range

intervallum = (i for i in range(1000))

sys.getsizeof(intervallum)
Out[61]: 120

Il generatore occupa circa 3 volte la memoria dell'oggetto range. Non ci si dovrebbe aspettare un comportamento equivalente o perlomeno simile?

Grazie a tutti
215 views

3 Answers

C
ChristianSt (1790 points)
3 9 25
answered Oct 28, 2020 by ChristianSt (1,790 points)
Stai comparando il size di sys.getsizeof(interval) e di sys.getsizeof(intervallum) giusto? Penso che sia dovuto dal fatto che l'oggetto range() contiene solo l'indice di partenza e di arrivo (quindi niente lista completa), mentre intervallum contiene al suo interno gia' la lista creata e completa. Quindi range dovrebbe occupare meno spazio visto che deve solo ricordarsi l'index start e l'index end, mentre il generator deve tenersi la lista in memoria. Questa e' solo una idea, ma sarebbe interessante approfondire :)
AdSum (16290 points)
9 20 134
answered Oct 28, 2020 by AdSum (16,290 points)
Range occupa meno spazio perchè funziona in una maniera particolare. Mentre con le liste e le tuple devi mantenere tutti gli oggetti in memoria (e quindi occupi spazio proporzionalmente alla lunghezza della lista) range non ne ha bisogno. Range viene utilizzato quando tu non devi accedere immediatamente a tutti i valori, ma ne necessiti solo una parte. Un esempio è il for, tu hai bisogno di un valore di "i" alla volta, averli tutti in memoria è solamente uno spreco di risorse! Quindi range, attraverso un suo algoritmo particolare (di cui onestamente non conosco i dettagli) genera i valori nel momento in cui hai bisogno di utilizzarli e per questo finisci per occupare meno spazio dei valori stessi, semplicemente ancora non sono stati generati.
andrea.sterbini (172680 points)
511 927 1776
answered Oct 28, 2020 by andrea.sterbini (172,680 points)

penso che siano due generatori uno dentro l'altro, la scritta con le parentesi tonde

(i for i in <iteratore/generatore>)

produce un generatore, ma al suo interno hai messo range che a sua volta è un generatore, quindi immagino che le dimensioni siano leggermente maggiori