Pythonリストと配列-いつ使用するのですか?


375

1次元配列を作成する場合は、それをリストとして実装するか、標準ライブラリの「配列」モジュールを使用できます。私は常に1次元配列のリストを使用しています。

代わりにアレイモジュールを使用する理由または状況は何ですか?

パフォーマンスとメモリの最適化のためですか、それとも明らかなものがないですか?

回答:


438

基本的に、Pythonリストは非常に柔軟であり、完全に異種の任意のデータを保持でき、償却済みの一定時間内に非常に効率的に追加できます。リストを時間効率よく、面倒なく縮小および拡大する必要がある場合は、それらを使用する方法です。ただし、C配列よりもはるかに多くのスペースを使用します

array.array型が、一方、Cアレイ上だけ薄いラッパーです。同じタイプの同種のデータのみを保持できるためsizeof(one object) * length、メモリのバイトのみを使用します。ほとんどの場合、C配列を拡張機能またはシステムコール(ioctlまたはfctnl)に公開する必要がある場合に使用します。

array.arrayまた、Python 2.x()で可変文字列を表すための妥当な方法array('B', bytes)です。ただし、Python 2.6+および3.xでは、可変バイト文字列がとして提供されbytearrayます。

ただし、数値データの同種配列で数学を実行する場合は、複雑な多次元配列での演算を自動的にベクトル化できるNumPyを使用する方がはるかに便利です。

長い話を短くするようにするにはarray.arrayあなたは理由のためのデータの均質なC配列必要がある場合に有用である数学をやっ以外を


9
numpy.ndarrayはarray.arrayと同じメモリフットプリントを持っていますか?
Gordon Bean

6
@Gordon、それは大きな連続した配列の場合にも非常によく似ているはずです。どちらもsizeof(element)×(要素の数)バイトと、オーバーヘッド用の小さな固定ヘッダーを必要とします。しかし、ndarray大きな配列にメモリを割り当てるためのいくつかのプラグイン可能な戦略を不連続とスパース配列を扱うためのいくつかの高度なオプションを持っている、と私は思う...これらの高度な機能のいくつかは、それをユーザーになります少ない他の人が使用してパフォーマンスを向上させる一方で、メモリをよりメモリ。
Dan Lenski 2014年

また、micropythonを使用してマイクロコントローラーをプログラミングする場合など、メモリに問題がある場合にも有用です
janscas

配列のi番目の要素を一定の時間でルックアップできますが、リンクリストでは最悪の場合、順序は「n」になります。Pythonリストのi番目の要素のルックアップ時間は何ですか?
ニッシュの追求の幸福2017

7
@ NithishInpursuitOfhappiness、Pythonリストはリンクリストではありません。内部的には配列として表され、JavaのArrayListと同じ時間の複雑さの特性を持っています。したがって、Pythonリストのi番目の要素の取得と設定には一定の時間がかかります。要素がPythonリストに追加されると、配列のサイズがスペース不足になると2倍になるため、一定の償却時間がかかります。要素をシフトする必要があるため、Pythonリストの途中で要素を挿入または削除するには、O(n)時間かかります。参考のために、wiki.python.org
moin

66

ほとんどの場合、通常のリストが適切な選択です。配列モジュールは、C配列のシンラッパーのようなもので、厳密に型指定されたコンテナー(docsを参照)の一種を提供し、ビルドの一部ではない、signed / unsigned shortやdoubleなどのCのような型にアクセスできます。タイプ。本当に必要な場合にのみ配列モジュールを使用します。それ以外の場合はすべてリストを使用します。


3
可能ですが、実際には使用していませんが、いくつかのマイクロベンチマークを実行すると興味深いでしょう。
アンドレ・

13
実際、私は簡単なテストを行いました-100Mエントリのリストを合計し、対応する配列を使って同じテストを行いました。実際、リストは約10%高速でした。
萌え

38
配列の「生」データに対する操作は、配列の読み取りまたは書き込み時にPythonオブジェクトを継続的に作成および破棄する必要があるため、リストはより高速です。
tzot 2008年

7
@Moe、上記の私の回答で指摘したように、Pythonの組み込み関数array数学を行うためのものではありませんndarray10 ^ 8の数値の配列を合計するためにNumPyを試してみると、完全に吹き飛ばされlistてしまいます。@tzotは、組み込みのarray計算が遅い理由について正しい考えを持っています。
Dan Lenski 2014

2
私はそれをテストしました、私のマシンではnumpyが86.6倍高速です。
マーク

53

アレイモジュールは、なぜそれを使用するのかわからない場合におそらく必要のないものの1つです(そして、私はそれを降順で言っているわけではないことに注意してください!) 。ほとんどの場合、配列モジュールはCコードとのインターフェースに使用されます。パフォーマンスに関する質問へのより直接的な回答を提供するには:

一部の用途では、配列はリストよりも効率的です。変更されないことがわかっている配列を割り当てる必要がある場合は、配列を高速化し、使用するメモリを少なくすることができます。GvRには、アレイモジュールが勝者となる最適化の逸話があります(長い記事ですが、それだけの価値があります)。

一方、リストが配列よりも多くのメモリを消費する理由の一部は、割り当てられたすべての要素が使用されると、Pythonがいくつかの追加の要素を割り当てるためです。つまり、アイテムをリストに追加する方が高速です。したがって、アイテムの追加を計画している場合は、リストが適しています。

TL; DR例外的な最適化が必要な場合、またはCコードとのインターフェースが必要な場合(およびpyrexを使用できない場合)は、配列のみを使用します。


1
具体的な例として+1と速度の利点について言及します。一番上の答えは、「時間とメモリのトレードオフはありますか?」そして「これは非常に難解な低メモリケースではない用途はありますか?」
leewz 2014

@leewz正確に、これは答えと見なされるべきです。
Gauri Shankar Badola

21

それはトレードオフです!

それぞれの長所:

リスト

  • フレキシブル
  • 異質である可能性があります

配列(例:numpy配列)

  • 均一な値の配列
  • 同種の
  • コンパクト(サイズ)
  • 効率的(機能性と速度)
  • 便利

2
質問はPythonの配列モジュールを参照しています。派手な配列ではありません。彼らはサイズ効率を除いて多くのプロがいません。彼らは速くありません。
NONONONONO

14

配列はより効率的に(つまり、メモリの連続ブロック対Pythonオブジェクトへのポインタとして)格納されると私は理解していますが、パフォーマンス上の利点は知りません。さらに、配列では同じタイプのプリミティブを格納する必要がありますが、リストは何でも格納できます。


8

標準ライブラリ配列は、intのリストを文字列に変換してwaveファイルなどに書き込むなど、バイナリI / Oに役立ちます。そうは言っても、多くの人がすでに述べたように、実際の作業を行う場合は、NumPyの使用を検討する必要があります。



5

配列は特定のタイプにのみ使用できますが、リストは任意のオブジェクトに使用できます。

配列は1つのタイプのデータのみを含むこともできますが、リストにはさまざまなオブジェクトタイプのエントリを含めることができます。

配列は数値計算にとってもより効率的です。


4
組み込みのPython配列は、パフォーマンスに関しては効率的ではなく、メモリに関してのみです。
tzot 2008年

配列が処理の点でより効率的な場合があります。:以下の私の記事を参照してください stackoverflow.com/questions/176011/...
ジェイソン・ベイカー

0

numpy配列とリストの重要な違いは、配列スライスは元の配列のビューであることです。つまり、データはコピーされず、ビューへの変更はソース配列に反映されます。


0

この答えは、ListとArrayをいつ使用するかに関するほぼすべてのクエリを要約したものです。

  1. これら2つのデータ型の主な違いは、それらに対して実行できる操作です。たとえば、配列を3で除算すると、配列の各要素が3で除算されます。リストでは同じことはできません。

  2. リストはpythonの構文の一部なので、宣言する必要はありませんが、使用する前に配列を宣言する必要があります。

  3. 異なるデータ型の値をリスト(異種)に格納できますが、配列では同じデータ型(同種)の値のみを格納できます。

  4. 配列は機能が豊富で高速なので、リストと比較して、算術演算や大量のデータの格納に広く使用されています。

  5. 配列は、リストと比較して必要なメモリが少なくなります。


0

パフォーマンスに関して、Pythonリスト、配列、およびnumpy配列を比較するいくつかの数値を示します(すべて2017 Macbook ProのPython 3.7で)。最終結果は、これらの操作に対してPythonリストが最速になることです。

# Python list with append()
np.mean(timeit.repeat(setup="a = []", stmt="a.append(1.0)", number=1000, repeat=5000)) * 1000
# 0.054 +/- 0.025 msec

# Python array with append()
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a.append(1.0)", number=1000, repeat=5000)) * 1000
# 0.104 +/- 0.025 msec

# Numpy array with append()
np.mean(timeit.repeat(setup="import numpy as np; a = np.array([])", stmt="np.append(a, [1.0])", number=1000, repeat=5000)) * 1000
# 5.183 +/- 0.950 msec

# Python list using +=
np.mean(timeit.repeat(setup="a = []", stmt="a += [1.0]", number=1000, repeat=5000)) * 1000
# 0.062 +/- 0.021 msec

# Python array using += 
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a += array.array('f', [1.0]) ", number=1000, repeat=5000)) * 1000
# 0.289 +/- 0.043 msec

# Python list using extend()
np.mean(timeit.repeat(setup="a = []", stmt="a.extend([1.0])", number=1000, repeat=5000)) * 1000
# 0.083 +/- 0.020 msec

# Python array using extend()
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a.extend([1.0]) ", number=1000, repeat=5000)) * 1000
# 0.169 +/- 0.034
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.