По-видимому list(a)
, не перераспределяет, [x for x in a]
перераспределяет в некоторых точках, и [*a]
перераспределяет все время ?
Вот размеры n от 0 до 12 и результирующие размеры в байтах для трех методов:
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
Вычисляется следующим образом, воспроизводится в repl.it , используя 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]))
Так как это работает? Как [*a]
перераспределить? На самом деле, какой механизм он использует для создания списка результатов из заданного ввода? Он использует итератор a
и использует что-то вроде list.append
? Где находится исходный код?
( Colab с данными и кодом, который произвел изображения.)
Увеличение до меньшего n:
Уменьшение до большего n:
list(a)
работает полностью в C; он может распределять внутренний буферный узел по узлам, когда он повторяется a
. [x for x in a]
просто использует LIST_APPEND
много, поэтому он следует обычному шаблону «немного перераспределить, перераспределить при необходимости» обычного списка. [*a]
использует BUILD_LIST_UNPACK
, что ... я не знаю, что это делает, за исключением, по-видимому, чрезмерного распределения все время :)
list(a)
и [*a]
они идентичны, и оба слишком распределены по сравнению с [x for x in a]
, так что ... sys.getsizeof
возможно, это не тот инструмент, который можно использовать здесь.
sys.getsizeof
это правильный инструмент, он просто показывает, что list(a)
раньше перераспределять. Фактически, что нового в Python 3.8 упоминает это: «Конструктор списка не перераспределяет [...]» .
[*a]
видимому, ведет себя как использованиеextend
в пустом списке.