Al parecer, list(a)
¿no se sobreasigna, se [x for x in a]
sobreasigna en algunos puntos y se [*a]
sobreasigna todo el tiempo ?
Estos son los tamaños n de 0 a 12 y los tamaños resultantes en bytes para los tres métodos:
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
Calculado así, reproducible en repl.it , usando 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]))
¿Entonces, cómo funciona esto? ¿Cómo se [*a]
sobreasigna? En realidad, ¿qué mecanismo utiliza para crear la lista de resultados a partir de la entrada dada? ¿Utiliza un iterador a
y usa algo como list.append
? ¿Dónde está el código fuente?
( Colab con datos y código que produjeron las imágenes).
Acercamiento a n menor:
Alejar a n mayor:
list(a)
opera completamente en C; puede asignar el búfer interno nodo por nodo a medida que se repite a
. [x for x in a]
simplemente usa LIST_APPEND
mucho, por lo que sigue el patrón normal de "sobreasignar un poco, reasignar cuando sea necesario" de una lista normal. [*a]
usos BUILD_LIST_UNPACK
, que ... No sé qué hace eso, aparte de aparentemente
list(a)
y [*a]
son idénticos, y tanto overallocate en comparación con [x for x in a]
, por lo que ... sys.getsizeof
no podría ser la herramienta adecuada para usar aquí.
sys.getsizeof
es la herramienta correcta, solo muestra que list(a)
solía sobreasignar. En realidad, lo nuevo en Python 3.8 lo menciona: "El constructor de la lista no sobreasigna [...]" .
[*a]
parece comportarse como si se usaraextend
en una lista vacía.