どうやらlist(a)
、overallocateない[x for x in a]
いくつかの点でoverallocatesは、と[*a]
overallocates すべての時間を?
ここでは三つの方法のためにサイズ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で再現可能パイソン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]
overallocate?実際には、どのようなメカニズムには、与えられた入力から結果リストを作成するために使用しますか?それはオーバーイテレータ使用していますa
のようなものと使用をlist.append
?ソースコードはどこですか?
(データとコードとのコラボ画像を生成しました。)
小さいnまでにズーム:
大きなnにズームアウト:
[*a]
内部での同等のCをやっています:
- 新しいを作成し、空
list
- コール
newlist.extend(a)
- 戻り値
list
。
あなたがテストにを展開するのであれば:
from sys import getsizeof
for n in range(13):
a = [None] * n
l = []
l.extend(a)
print(n, getsizeof(list(a)),
getsizeof([x for x in a]),
getsizeof([*a]),
getsizeof(l))
あなたはのために結果が表示されますgetsizeof([*a])
とl = []; l.extend(a); getsizeof(l)
同じです。
これは通常行うには正しいことです。ときextend
INGのあなたは、通常より後で追加するには期待している、と同様に一般開梱のためには、複数のものが次々に追加されることを想定しています。[*a]
通常のケースではありません。それに追加される複数のアイテムまたはイテレート可能オブジェクトが存在する前提list
(は[*a, b, c, *d]
)ので、割り当て超過は、一般的なケースでの作業を保存します。
By contrast, a list
constructed from a single, presized iterable (with list()
) may not grow or shrink during use, and overallocating is premature until proven otherwise; Python recently fixed a bug that made the constructor overallocate even for inputs with known size.
As for list
comprehensions, they're effectively equivalent to repeated append
s, so you're seeing the final result of the normal overallocation growth pattern when adding an element at a time.
明確にするために、これのどれも言語保証するものではありません。それはCPythonのは、それを実装して、どれだけです。Python言語仕様は、一般的に、特定の成長パターンと無関心されるlist
(保証償却別にO(1)
append
S及びpop
端からS)。コメントで述べたように、具体的な実装は3.9で再び変更します。それは影響しません一方で[*a]
、それはビルド一時的に使用されるどのような他の例影響を与える可能性がありtuple
、個々のアイテムのとextend
ではtuple
、それは今の複数のアプリケーションになっLIST_APPEND
割り当て超過が発生し、どのような数字は計算に入ったときに変更することができ、。