Wygląda na list(a)
to, że totalocate, [x for x in a]
totalocates w niektórych momentach i [*a]
totalocate przez cały czas ?
Oto rozmiary n od 0 do 12 i wynikowe rozmiary w bajtach dla trzech metod:
0 56 56 56
1 64 88 88
2 72 88 96
3 80 88 104
4 88 88 112
5 96 120 120
6 104 120 128
7 112 120 136
8 120 120 152
9 128 184 184
10 136 184 192
11 144 184 200
12 152 184 208
Obliczony w ten sposób, odtwarzalny w repl.it , przy użyciu Python 3. 8 :
from sys import getsizeof
for n in range(13):
a = [None] * n
print(n, getsizeof(list(a)),
getsizeof([x for x in a]),
getsizeof([*a]))
Więc: jak to działa? Jak działa [*a]
totalocate? Jakiego mechanizmu używa do tworzenia listy wyników na podstawie danych wejściowych? Czy używa iteratora a
i używa czegoś takiego list.append
? Gdzie jest kod źródłowy?
( Colab z danymi i kodem, który wytworzył obrazy).
Powiększanie do mniejszego n:
Pomniejszanie do większego n:
list(a)
działa całkowicie w C; może przydzielać wewnętrzny węzeł buforowy po węźle podczas iteracji a
. [x for x in a]
po prostu LIST_APPEND
dużo zużywa , więc podąża za normalnym wzorcem „ogólnie przydzielać trochę, w razie potrzeby ponownie przydzielać” normalnej listy. [*a]
używa BUILD_LIST_UNPACK
, które ... nie wiem, co to robi, poza tym, że najwyraźniej cały czas
list(a)
i [*a]
są identyczne, a obie overallocate porównaniu [x for x in a]
, więc ... sys.getsizeof
nie może być właściwym narzędziem do wykorzystania tutaj.
sys.getsizeof
to właściwe narzędzie, to po prostu pokazuje, że list(a)
używałeś do generalocate. Właściwie to, co nowego w Python 3.8 wspomina: „Konstruktor listy nie dokonuje ogólnej alokacji [...]” .
[*a]
wydaje się zachowywać jak używanieextend
na pustej liście.