2016-10-29 5 views
21

ich eine Liste haben my_list (die Liste enthält UTF-8-Strings):Warum eine sortierte Liste größer als eine unsortierte Liste ist

>>> len(my_list) 
8777 
>>> getsizeof(my_list)      # <-- note the size 
77848 

Aus irgendeinem Grund eine sortierte Liste (my_sorted_list = sorted(my_list)) verwendet mehr Speicher:

>>> len(my_sorted_list) 
8777 
>>> getsizeof(my_sorted_list)    # <-- note the size 
79104 

Warum gibt sorted eine Liste zurück, die mehr Speicherplatz als die ursprüngliche unsortierte Liste benötigt?

+1

Als [@ Jims Antwort] (http://stackoverflow.com/a/40317620/3124746) darauf hingewiesen, dass 'sortierte' erstellt neue Liste können Sie Geschichte mit folgen [meine letzte Frage (list() verwendet mehr Speicher als Listenverständnis)] (http://stackoverflow.com/questions/40018398/list-uses-more-memory-than-list-comprehension) es würde Ihnen einige Python-Einsichten geben. –

+1

@vishes_shell Oder auch https://stackoverflow.com/questions/7247298/size-of-list-in-memory (in 2011 gefragt) – jcuenod

+1

Ich mochte die Charts in Ihrer Antwort auf Ihre Frage @vishes_shell :-). Das einzige Problem, das ich bei diesen Fragen und Antworten sehe, ist, dass sie * plötzlich * plötzlich * obsolet werden können, weil wir es mit einem Implementierungsdetail zu tun haben: ( –

Antwort

18

Wie bei Ignacio points out liegt dies daran, dass Python etwas mehr Speicher als erforderlich zugewiesen hat. Dies wird durchgeführt, um O(1).appends auf Listen durchzuführen.

sortedcreates a new list aus der angegebenen Reihenfolge, sorts it in place und gibt es zurück. Um die neue Liste zu erstellen, Python extends an empty sized list with the one passed; Dies führt zu der beobachteten Überbelegung (die nach dem Aufruf von list_resize auftritt). Sie können die Tatsache bestätigen, dass die Sortierung nicht der Übeltäter ist, indem Sie list.sort verwenden; Der gleiche Algorithmus wird verwendet ohne eine neue Liste zu erstellen (oder, wie es bekannt ist, ist es durchgeführt in-Place). Die Größen dort, unterscheiden sich natürlich nicht.

Es ist erwähnenswert, dass dieser Unterschied meist vorhanden ist, wenn:

Also, mit einer Liste-comp:

l = [i for i in range(10)] 

getsizeof(l)   # 192 
getsizeof(sorted(l)) # 200 

oder eine Liste wörtliche:

l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

getsizeof(l)   # 144 
getsizeof(sorted(l)) # 200 

die Größen sind kleiner (mehr bei Verwendung von Literalen).

Beim Erstellen über list ist der Speicher immer überzuordnet; Python knows the sizes und preempts zukünftige Änderungen durch ein wenig von der Größe basierend über Zuweisung:

l = list(range(10)) 

getsizeof(l)   # 200 
getsizeof(sorted(l)) # 200 

So haben Sie keinen beobachtete Unterschied in den Größen der Liste erhalten (s).


Als abschließende Bemerkung, muss ich darauf hinweisen, dass dieses Verhalten spezifischen die C Implementierung von Python d.h CPython ist.Es ist ein Detail, wie die Sprache implementiert wurde und als solches sollten Sie sich nicht auf irgendeine verrückte Weise darauf verlassen.

Jython, IronPython, PyPy und jede andere Implementierung haben möglicherweise nicht das gleiche Verhalten.

13

Die list resize operation overallocates, um an die Liste zu amortisieren am Anfang gegen eine Liste mit dem Compiler vor.

+1

Danke für den Link zu Pythons Code! Das ist großartig ... Ich hätte es akzeptiert, aber die Details in @ Jims Antwort haben mich überzeugt. – jcuenod

Verwandte Themen