Rõ ràng list(a)
không phải là tổng thể, [x for x in a]
tổng thể tại một số điểm, và [*a]
tổng thể mọi lúc ?
Dưới đây là kích thước n từ 0 đến 12 và kích thước kết quả tính bằng byte cho ba phương thức:
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
Được tính toán như thế này, có thể tái tạo tại repl.it , sử dụng 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]))
Vì vậy, làm thế nào điều này làm việc? Làm thế nào để [*a]
tổng thể? Trên thực tế, nó sử dụng cơ chế nào để tạo danh sách kết quả từ đầu vào đã cho? Nó sử dụng một iterator hơn a
và sử dụng một cái gì đó như thế list.append
nào? Mã nguồn ở đâu?
( Colab với dữ liệu và mã tạo ra hình ảnh.)
Phóng to đến n nhỏ hơn:
Thu nhỏ đến n lớn hơn:
list(a)
hoạt động hoàn toàn trong C; nó có thể phân bổ nút đệm nội bộ theo nút khi nó lặp lại a
. [x for x in a]
chỉ sử dụng LIST_APPEND
rất nhiều, vì vậy nó tuân theo mô hình "tổng thể một chút, phân bổ lại khi cần thiết" của một danh sách bình thường. [*a]
sử dụng BUILD_LIST_UNPACK
, mà ... tôi không biết nó làm gì, ngoài việc phân bổ quá mức mọi lúc :)
list(a)
và [*a]
giống hệt nhau và cả hai tổng thể so với [x for x in a]
, vì vậy ... sys.getsizeof
có thể không phải là công cụ phù hợp để sử dụng ở đây.
sys.getsizeof
là công cụ phù hợp, nó chỉ hiển thị list(a)
được sử dụng để tổng thể. Trên thực tế Có gì mới trong Python 3.8 đề cập đến nó: "Trình xây dựng danh sách không tổng thể [...]" .
[*a]
dường như hoạt động như sử dụngextend
trong danh sách trống.