【Python】 リスト とは

python_list

今回はpythonのビルトインオブジェクトの一つである、リスト について説明します。ビルトインオブジェクトは汎用性が高いことから、使い方を定着させることで実現できるコードの幅が格段に広がります。一つずつ確実に身につけていきましょう。


今年はアウトプットを多めにすると決断したので、投稿頻度を挙げていきますので、よろしくおねがいします。まずはリストとは何かという初歩的なところから順に解説していきます。

リスト について

リストとは「オブジェクトの集合」を表していて、要素が一定の順序で並ぶという特性を有するオブジェクトの一つです。例として、A~Hの8個の要素からなるリストを変数Xで定義した際のイメージを図に示します。オブジェクトA~Hが順番に並んでおり、オブジェクト内の特定の要素を取り出すことができます。ここで、「要素を取り出す」ためにオブジェクトが規則的に並んでいるということがわかります。つまり、Cを取り出したい場合、オブジェクトの3番目の値を取り出せば良い、といった具合で特定の要素を参照可能としています。

リストの概念

上記では、要素が文字のみでしたが、リストは、あらゆるオブジェクトを構成要素とすることができます。そのため、リスト自身も構成要素となりうるのが特徴です。つまり、リストの要素にさらにリストを作ることができます。

リスト の特徴

この章では、リストの特徴を挙げていきます。

オブジェクトを一定の間隔で並べたもの

上述の通り、リストを構成するオブジェクトは一塊のものとして扱えます。要素は、左から右へ、一定の順序で並べられます。つまり、シーケンスの一種であるということです。

インデックスによって要素の参照が可能

リストは文字列と同じようにインデックスを利用することで、構成要素にアクセスできます。ここで、インデックスとはオフセットのような意味合いで使用しています。
一定の順序で並んでいることから、インデックスによるアクセスやスライシングや連結といった操作にも対応できます。(スライシング、連結については後述します。)

リスト長の可変、複数種のオブジェクトの混合、

リストが文字列と異なる点として、要素数(長さ)が自由に変えられる点が挙げられます。また、文字列のように特定の種類の要素だけから構成されるだけでなく、複数種類のオブジェクトを混合させることが可能です。リストの中にリストを入れるという、ネストにも対応できます。

シーケンスの一種だが、変更可能

インデックスを指定して特定の要素を削除する、特定の要素に変更を加える、新たな要素を追加することが可能です。以下に例を示します。
Lというリストを定義して、左の要素を0⇨100に変更して変数Lのオブジェクトを表示しています。
下のコードから、リストが更新されていることがわかります。

L=[0,1,2,]
L[0]=100
L
→[100,1,2]

また、ここで一点注意事項があります。別変数にて同じリストオブジェクトを参照している場合、新たに指定した変数にて要素の変更を行なった場合、元の変数に対してオブジェクトの変更がなされています。以下に例を示します。先ほどのLで定義したリストに対して、A=Lとした別変数を用意します。Aに対して要素の変更を行なったのに対し、Lのオブジェクトを出力したところ、Lの要素も変更されています。これは、下図のように二つの変数が同じオブジェクトを参照しているため、オブジェクトの要素変更が両方に反映されるということです。

L=[0,1,2,]
A=L
A[0]=100
L
→[100,1,2]

基本的な演算

python にて使用するリストの基本的な演算、操作について説明します。
以下まとめた表を示します。基本的なコードを網羅しているつもりですのでよろしければ参考にして頂けたらと思います。

操作・演算内容
L=[]要素を含まないリストの作成
L=[0 , 1 , 2 , 3]4つの要素を含むリストの作成
L=[‘a’ , [‘b’ , ‘c’]]リストのネストの作成
L[i]インデクシング(i番目の要素を取得)
L[i][j]インデックスのインデクシング(i番目の要素のj番目の要素を取得)
L[i : j]スライシング(i+1番目からj番目までの要素を取得)
len(L)長さの確認
L1+L2連結
L*3Lを3回繰り返し
L.append(‘A’)リストの拡張
L.extend([ ‘A’ , ‘B’ , ‘C’ ])リストの拡張(リスト追加)
del L[i]i番目の要素を削除
L[i] = 1i番目の値を1に変更
range(4)整数のリスト
L=[x**2 for x in range(5)]リスト内包表記
リストの基本操作

リストのコード例

基本操作

+は連結、*は繰り返しの処理となります。リストは文字列と同様に、シーケンスオブジェクトのため、他の多くの操作、演算も同様に処理可能です。

[1, 2, 3]+[4, 5, 6]
→[1, 2, 3, 4, 5, 6]

['Berry','Very']*2
→['Berry','Very', 'Berry','Very']

+の処理の場合、同じ型のオブジェクトでなければできない点に注意してください。どうしても連結したい場合は文字列にへんかんしてから連結する手法がいいと思います。

インデクシング、スライシング、行列の表現

文字列と同様に、インデクシングやスライシングを行えます。ただ、リストに対してインデクシングを行なった際には出力されるオブジェクトが変化する可能性があります。これは、リストは複数のオブジェクトを混合可能である特徴から来ています。
また、リストに対してスライシングを行うと、新たなリストが結果として得られます。つまり、元のオブジェクトは保持されます。インデクシング、スライシングの例を以下に示します。

L=['Berry','Very','Vary']
L[1]
→'Very'

L=['Berry','Very','Vary']
L[1:]
→['Very', 'Vary']

リストを用いた行列の実現は、リストの中にリストをネストすることが最も簡単でしょう。以下に2×2の行列の例を示します。

matrix = [[1,2],[3,4]]

このように表記することで、二次元配列を実現できます。さらに高度な配列として、3次元以上の行列も実現可能ですが、numpyを使用する方がいいでしょう。numpyについて記事を書く際に触れようと思います。

リストのメソッド

文字列と同様に、リストにも固有のメソッドが用意されています。メソッドとは、特定のオブジェクトに対して使用できる関数のことです。ビルトイン関数ではメソッドはすでに与えられているため、追加でインストールする必要はありません。

リストのメソッドで最も使用頻度が高いものは、appendです。appendメソッドはリストの末尾に要素を追加するもので、リストに一つのオブジェクトを加えます。(表にも記載あります)

リストに要素を追加する方法として、「+」を使うことが容易に想定されます。
L.append(‘A’)と、L+[‘A’]は同じ結果になるように見えますが、前者は元のリストそのものに変更がなされるのに対して、後者は新たなリストが作成されます。そのため、appendは新たなリストを作らないぶん、コードの実行時間が短く済みます。文字列 ‘Berry’を追加するコードで上記に通りの書き方で速度を比較したところ、メソッドを使用した方が、4.7倍早くコード処理ができました。シンプルで要素データが少ないものでこれだけ差があるため、より複雑なコードの際には、より顕著にappendメソッドの優位性があるかと思います。

リスト内包表記

では最後にリスト内包表記について説明をします。

リスト内包表記の概要

リストの要素に順に変更を加えようとする際、for文を使用することで処理できます。例えば、全ての要素に3を足したい場合、以下のコードが考えられます。

L = [1, 2, 3]
for i in range(Len(L)):
  L[i] +=3
L
→[4, 5, 6]

for文を使用するのは最良の方法とは言えません。というのも、単純な処理に対してコードが長くなるためです。現在のPythonではリスト内包表記を使用して同じことができます。上記と同様の処理を以下に示します。

L = [x+3 for x in L]

2つのコードを比較すると、コードが少なく済んでいることがわかります。コードが少ないため、処理速度も上がるでしょう。しかし、上記二つのコードは全く同じものではありません。リスト内包表記の場合、リストオブジェクトが新たに作られます。しかし、同様のものとして利用できるケースが多いため、forループよりも便利に使えるツールだと思っていただいて大丈夫です。

リスト内包表記の基礎

リスト内包表記には必ず角括弧[ ]を使います。角括弧をつける理由は、出力が新しいリストを作ることにあるためです。括弧の左側にはループ変数(上記ではx)の入った式が入ります。ループ変数とは、ループ内での処理をする際に一時的に値を保持するものです。式を書いた後は、forループの前半と同じような記載をします。その中で、ループ変数と反復処理の対象とするオブジェクトを記載します。

コード実行時にはLの要素が順にxに代入されていき、その都度記載した式を適用、結果を新たなリスト(上記ではL)に格納します。

メリット

リスト内包表記のメリットはいくつかあります。

コードが簡潔になる

forループを使用しても同じ結果が得られるわけですが、上記のコードを比較した際に、リスト内包表記を使用した方がシンプルでわかりやすいと思います。複雑なコード実装をした際、できるだけしんぷるに記載しておかないとデバック時や、見直す際に余計な労力を割くこととなります。「できるだけシンプルに」コードを書くためにもリスト内包表記は有用です。

出力が必ずリストになる

これも大きなメリットになりますforループだと、出力のオブジェクトの型を自由に定義できますが、リスト内包表記であれば、出力は必ずリストになります。リストはビルトインオブジェクトであることから、その後のコード処理も行いやすくなります。

実行速度が速い

通常のforループと比較して、約2倍ほど実行速度が速いです。これは、反復がPythonのコードの段階で行われるものではなく、インタプリタ内部でCの段階で行われるためです。実装する対象が大規模なデータであればリスト内包表記が有用となります。

リスト内包表記で使用するループとif

リスト内包表記はforループのみでなく、後ろにifで始まるコードを記載可能です。すなわち、条件判定のロジックを追加できます。例として、0~14のうち、3で割り切れる数だけを抽出するコードを示します。

L=[x for x in range(15) if x%3 ==0]
→[0, 3, 6, 9, 12]

このように、単にforループでリストを作成するだけでなく、フィルターの機能を追加できるのです。

まとめ

今回はリストについて基本的なことから応用まで説明しました。リストは汎用性の高いオブジェクトであるので、特徴を理解して、コード実装することが望ましいです。また、構文は基本的に文字列と同じですが、独自のメソッドや、リスト内包表記を理解することで、より見やすく、質の高いコードが書けるようになります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


ABOUT US
shota_py
メーカー勤務のエンジニアです。 自分の趣味である、「電気回路」、「ガジェット」「株式投資」、「Python」に関する記事をつらつらと書いています