1. ホーム
  2. python

[解決済み] Pythonでfix size listを作るには?

2023-06-28 06:41:52

質問

C++で、次のような配列を作成することができます...

int* a = new int[10];

Pythonで、私はリストを宣言し、いくつかの項目を追加することができることを知っている、またはそのような。

l = [1,2,3,4]
l = range(10)

c++のように、与えられたサイズでリストを初期化し、代入を行わないようにすることは可能でしょうか?

どのように解決するのですか?

(tl;dr: あなたの質問に対する正確な答えは numpy.empty または numpy.empty_like を使用することができますが、あなたはおそらく気にしないでしょう。 myList = [None]*10000 .)

簡単な方法

リストをすべて同じ要素に初期化することができます。意味的に非数値(これを使用すると後でエラーが発生します、これは良いことです)を使用するか、0 のようなもの(珍しい? 疎な行列を書いている場合や「デフォルト」値が 0 であるべきで、バグについて心配していない場合に有用かもしれません)を使用するかはあなた次第です。

>>> [None for _ in range(10)]
[None, None, None, None, None, None, None, None, None, None]

(ここでは _ は単なる変数名なので i .)

このようにすることもできます。

>>> [None]*10
[None, None, None, None, None, None, None, None, None, None]

おそらく、これを最適化する必要はないでしょう。必要な都度、配列に追加することも可能です。

>>> x = []
>>> for i in range(10):
>>>    x.append(i)


単純な手法の性能比較

どれが一番いいのか?

>>> def initAndWrite_test():
...  x = [None]*10000
...  for i in range(10000):
...   x[i] = i
... 
>>> def initAndWrite2_test():
...  x = [None for _ in range(10000)]
...  for i in range(10000):
...   x[i] = i
... 
>>> def appendWrite_test():
...  x = []
...  for i in range(10000):
...   x.append(i)

python2.7での結果です。

>>> import timeit
>>> for f in [initAndWrite_test, initAndWrite2_test, appendWrite_test]:
...  print('{} takes {} usec/loop'.format(f.__name__, timeit.timeit(f, number=1000)*1000))
... 
initAndWrite_test takes 714.596033096 usec/loop
initAndWrite2_test takes 981.526136398 usec/loop
appendWrite_test takes 908.597946167 usec/loop

python 3.2での結果です。

initAndWrite_test takes 641.3581371307373 usec/loop
initAndWrite2_test takes 1033.6499214172363 usec/loop
appendWrite_test takes 895.9040641784668 usec/loop

見ての通り、このイディオムでは [None]*10000 を使うのが良いでしょう。しかし、もし代入よりも複雑なこと(例えばリストのすべての要素を生成したり処理したりするような複雑なこと)をしているなら、そのオーバーヘッドは無意味に小さくなってしまうでしょう。つまり、リストの要素で何か合理的なことをしているのであれば、そのような最適化は心配するのは時期尚早です。


未初期化メモリ

しかし、これらはすべてメモリを通過し、その過程で何かを書き込むため、非効率的です。C ではこれは異なります。初期化されていない配列はランダムなゴミメモリで満たされます (補足: システムから再割り当てされたものであり、そのようなゴミメモリは セキュリティリスク を割り当てたり、mlock に失敗したり、プログラムを閉じるときにメモリを削除しなかったりすると、セキュリティ上のリスクになります)。これは、高速化のために設計された選択です。C 言語のメーカーは、メモリを自動的に初期化しないほうがよいと考え、それは正しい選択でした。

これは漸近的な高速化ではありません (なぜなら、それは O(N) であるため)、例えば、実際に気になるもので上書きする前に、最初にメモリ ブロック全体を初期化する必要はありません。これは、もし可能であれば、次のようなものと同等です (擬似コード)。 x = list(size=10000) .

Pythonで同様のことをしたい場合は、以下のように numpy 数値行列/N次元配列操作パッケージがあります。具体的には numpy.empty または numpy.empty_like

これが本当の答えです。