テクノロジー

2023年1月1日

Python入門4 リストとタプル

リストやタプルが扱えるようになる

リスト

複数の値をまとめて扱うときはリスト型(list)という組み込み型を使います。この型は単にリストと呼ばれます。

リストへの格納

以下のように、1月と2月の平均気温を変数に格納し、表示するプログラムがあったとします。

january_average_temperature = 6
february_average_temperature = 7
print("各月の平均気温は、1月は{}度、2月は{}度です。".format(january_average_temperature, february_average_temperature))

もしこれが3月、4月、・・・、12月と続いていくと変数を12個用意することになります。12個くらいならば用意できるかもしれませんが、毎日の気温などとなると扱うのが難しくなってきます。変数名は「何が代入されているのかを一目で理解できるような名前」を意識することが大切ですが、数が増えると名前をつけるのも大変になってきます。

このような時にリストを使うことで、値をまとめて扱うことができます。リストは[]で囲い、,で値の間を区切ります。

monthly_average_temperatures = [6, 7, 9, 15, 20, 22, 27, 26, 23, 17, 12, 7]
print(monthly_average_temperatures)
print(type(monthly_average_temperatures))

出力すると「[6, 7, 9, 15, 20, 22, 27, 26, 23, 17, 12, 7]」「<class ‘list’>」と表示されます。

要素の取り出し

リストに入っている一つ一つの値を要素と呼びます。この要素は整数値の インデックス で指定することで取り出せます。インデックスは一番左が0からはじまります。最初のプログラムはリストを使うと次のように書けます。

monthly_average_temperatures = [6, 7, 9, 15, 20, 22, 27, 26, 23, 17, 12, 7]
print("各月の平均気温は、1月は{}度、2月は{}度です。".format(monthly_average_temperatures[0], monthly_average_temperatures[1]))

インデックスを変えることで、好きな要素を取り出すことができます。インデックスが1ではなく0からはじまることに注意しましょう。

print("各月の平均気温は、7月は{}度、12月は{}度です。".format(monthly_average_temperatures[6], monthly_average_temperatures[11]))

インデックスに負の値を指定すると、後ろからの順番になります。一番後ろを指定する-1はよく使います。

print("最後の月の平均気温は{}度です".format(monthly_average_temperatures[-1]))

なお、要素を取り出した場合のデータ型は、要素のデータ型になっています。

print(type(monthly_average_temperatures[0]))

実行すると「<class ‘int’>」と表示されます。

要素の書き換え

リストの要素を後から書き換えることも可能です。

print(monthly_average_temperatures[5])
monthly_average_temperatures[5] = 24
print(monthly_average_temperatures[5])

実行すると「22」「24」と表示されます。22度から24度に書き換えることができています。

スライスによる複数要素の取り出し

スライス という方法により、複数の要素をまとめて取り出すこともできます。:(コロン)を使い、[はじまりのインデックス:終了のひとつ後のインデックス]で指定します。3番目から7番目までを取り出すには次のように指定します。8番目までではなく、そのひとつ前の7番目までであることに注意しましょう。

print(monthly_average_temperatures[3:8])

実行すると「[15, 20, 24, 27, 26]」と表示されます。スライスを使った場合、取り出したものもリストになっています。
取り出す間隔(ステップ数)も指定することができます。[はじまりのインデックス:終了のひとつ後のインデックス:ステップ数]の形式にします。0番目から6番目までをひとつ飛ばしで取り出すには次のように指定します。

print(monthly_average_temperatures[3:8])

実行すると「[15, 20, 24, 27, 26]」と表示されます。スライスを使った場合、取り出したものもリストになっています。

取り出す間隔(ステップ数)も指定することができます。[はじまりのインデックス:終了のひとつ後のインデックス:ステップ数]の形式にします。0番目から6番目までをひとつ飛ばしで取り出すには次のように指定します。

print(monthly_average_temperatures[0:7:2])

実行すると「[6, 9, 20, 27]」と表示されます。

指定する際は、一部を省略することもできます。0番目から最後までを5つ飛ばしで取り出すには次のように指定します。

print(monthly_average_temperatures[::5])

実行すると「[6, 24, 12]」と表示されます。
ステップ数に負の値を入れると、後ろから順番に取り出すこともできます。

print(monthly_average_temperatures[::-1])

要素の長さ

リストに対しては、len関数を使うことでリストに含まれる要素数を整数値で取得することができます。この要素数を、リストの長さ(length)と呼ぶこともあります。len関数の名称もlengthから来ています。

print(len(monthly_average_temperatures))

実行すると「12」と表示されます。

数値以外の要素

リストには数値に限らず、文字列なども入れることができます。リストをリストの要素とすることもできます。また、異なるデータ型をひとつのリストに混ぜることもできます。

months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
odd_and_even = [[0, 2, 4, 6, 8], [1, 3, 5, 7, 9]]
mixed = [-5.5, "Python", 270, ["a", "b", "c"]]

リストが持つメソッド

リストはさまざまなメソッドを持っており、特にappendメソッドはよく使われます。リストの1番後ろに要素を追加するメソッドです。

numbers = [0, 1, 2, 3]
numbers.append(4)
print(numbers)

実行すると「[0, 1, 2, 3, 4]」と表示されます。

要素の入っていない、空のリストを作っておいて、後からappendメソッドで追加していく使われ方が多いです。

texts = []
texts.append("alpha")
texts.append("beta")
print(texts)

《代入してはいけない》

よくある間違いが、numbers = numbers.append(4)のように代入をしてしまうことです。appendメソッドは使った時点で新しい要素がリストに追加されており、代入を使うとおかしなことになります。

# 間違い例
numbers = [0, 1, 2, 3]
numbers = numbers.append(4)
print(numbers)
print(type(numbers))

実行すると「None」「<class ‘NoneType’>」と表示されます。ここで表示されている”None”は”None”という文字列ではなくて、NoneTypeという特別なデータ型です。今後関数やメソッドを自作する方法を知ると分かってくる言い方として「リストのappendメソッドはNoneを返している」と表現できます。

このことをより理解するために、次のようなプログラムも動かしてみます。

numbers = [0, 1, 2, 3]
print(numbers.append(4))
print(numbers)

実行すると「None」「[0, 1, 2, 3, 4]」と表示されます。appendメソッドをprint関数に入れると”None”が表示されますが、この時新しい要素4の追加は行われています。

なぜこの間違いがよくあるかと言うと、メソッドを使った後代入するという操作をすることもあるからです。

例えば文字列のcapitalizeメソッドです。

text = "python"
text.capitalize()
print(text)
capitalized_text = text.capitalize()
print(text)
print(capitalized_text)

実行すると「python」「python」「Python」と表示されます。メソッドを使った時に文字列自身は書き換わっておらず、代入する必要があることが分かります。
文字列メソッド — Python 3.7.3 ドキュメント

最初の文字を大文字にし、残りを小文字にした文字列のコピーを返します。

公式ドキュメントの説明にもこのようにありますが、appendメソッドに対応させて書くと、「文字列のcapitalizeメソッドは最初の文字を大文字にした文字列のコピーを返している」と表現できます。

リストの演算

+を使うことで、リストを結合することができます。

print([1, 2, 3] + [4, 5, 6])

実行すると「[1, 2, 3, 4, 5, 6]」と表示されます。

タプル

リスト型と似たものにタプル型(tuple)があります。この型はリスト同様、単にタプルと呼ばれます。

整数型(int)や浮動小数点型(float)をまとめて数値型と呼ぶように、リストやタプルのことを シーケンス型 と呼びます。また、少し区別されますが、文字列もシーケンス型の仲間です。

リストとの違い

タプルはリスト同様に複数の要素を格納することができます。ただし、タプルは一度定義すると要素の変更ができません。要素を追加をすることもできません。

タプルへの格納

タプルは()で囲い、,``で値の間を区切ります。

user_ids = ("A081", "A114", "A186")
print(user_ids)
print(type(user_ids))

実行すると「(‘A081’, ‘A114’, ‘A186’)」「<class ‘tuple’>」と表示されます。

要素の取り出し

リストと同様にインデックスを指定して要素を取り出せます。

print(user_ids[0])

ただし、これを左辺に持ってきて要素を書き換えるということはできません。

*以下はエラーになる例です。

user_ids[0] = "A082"

実行すると「TypeError: ‘tuple’ object does not support item assignment」というエラーメッセージが表示されます。タプルには要素を書き換える機能はないということを示しています。

要素の書き換えが必要な際は、リストを使うといった他の書き方が望ましいです。user_ids = ("A082", "A114", "A186")のように同じ変数名のタプルを作りなおすことは可能ですが、読みにくいプログラムとなる可能性が高いです。

*以下がエラーを解消した例です。

user_ids = ["A081", "A114", "A186"]
print(user_ids)
print(type(user_ids))
user_ids[0] = "A082"
print(user_ids)

括弧はなくても良い

タプルを作る際に必要なのは,のみであり、()は見やすくするためにつけられます。

普通このような書き方はしませんが、以下のようにできるということです。

user_ids = "A081", "A114", "A186"
print(user_ids)
print(type(user_ids))

実行すると「(‘A081’, ‘A114’, ‘A186’)」「<class ‘tuple’>」と括弧があった場合と同じ表示がされます。

一見タプルに必要なものは()の方にも思えてしまうので間違えやすいのが、要素がひとつのタプルの作成方法です。要素がひとつのタプルを作る時はuser_ids = ("A081")ではなく、user_ids = ("A081",)またはuser_ids = "A081",のようにする必要があります。

複数の変数を同時に代入することが可能でしたが、これは左右両辺がタプルになっているということです。次の2行は同じことを表しますが、括弧をつけない書き方の方が普通です。

s, t = 100, 200
(s, t) = (100, 200)

よって、次のようなことができます。

user_ids = ("A081", "A114", "A186")
user_id1, user_id2, user_id3 = user_ids

このことは、関数やメソッドの作り方を覚える際にもう一度確認します。タプルは書き換えができないという特徴よりも、こういった書き方の中での登場の方が目にする機会が多いかもしれません。

なお、空のタプルを作るには括弧がなくてはなりません。

empty_tuple = ()
print(empty_tuple)

実行すると「()」と表示されます。

listやtupleという命名に注意

text = "python"というような安易な変数名はサンプルコードにも使ってきましたが、同じような気持ちでlist = [0, 1, 2]tuple = ("A", "B")という命名は絶対にしてはいけません。

なぜならば、list関数やtuple関数が存在しているからです。それぞれリストに変換する関数、タプルに変換する関数です。整数型に変換するint関数や浮動小数点数型に変換するfloat関数があったのと同様です。

以下のコードはタプルをリストに変換しています。

user_ids = ("A081", "A114", "A186")
print(user_ids)
print(list(user_ids))

実行すると「(‘A081’, ‘A114’, ‘A186’)」「[‘A081’, ‘A114’, ‘A186’]」と表示されます。

もしlistという名前の変数を作ってしまうと、その後list関数を使った場合にエラーとなります。

*以下はエラーになる例です。

list = [0, 1, 2]
print(list(user_ids))

実行すると「TypeError: ‘list’ object is not callable」というエラーメッセージが表示されます。list関数がリスト型になってしまい、使えなくなっています。

元に戻す場合は、Colabであれば「ランタイム」の中から「ランタイムの再起動…」を選びます。そうすることではじめの状態に戻すことができます。Jupyter Notebookであれば「Kernel」の中から「Restart」を選びます。

特にリストに対しての安易な命名としてlistというのはついしてしまいそうなことなので、注意しましょう。命名した時点ではエラーにはならないため、気がつくのが遅れてしまうこともありえます。

参考文献

3.1.3. リスト型 (list) — Python 3.7.3 ドキュメント

シーケンス型 — list, tuple, range — Python 3.7.3 ドキュメント

ダイビックのことをもっと知ってみませんか?