こんにちは、ナナです。
リストの次に紹介するコンテナ第2弾は「タプル(tuple)」です。
リストオブジェクトは生成後でも要素の値を変更することができますが、「タプル」では一度生成した後は要素を変更できないのが特徴です。
本記事では次の疑問点を解消する内容となっています。
では、「タプル」の扱い方について学んでいきましょう。
『タプル』の定義方法と使い方
はい、はーい、僕がやってきましたよー。
あーなるほどー、今日は「タプル」ですね。・・・っで「タプル」って何ですか?
「リスト」は普段の生活の中でも使う言葉だけど、「タプル」って中々聞きなれない言葉ですよね。僕も日常で聞くことはありませんね。
「タプル」はデータ構造としては「リスト」と一緒なんですよ。でも、一度作ったら変えられないんです。
「タプル」は「リスト」とデータ構造が同じなため、セットで覚えるとわかりやすいです。
タプルオブジェクトの定義方法
タプルオブジェクトの定義方法は、次の書式で記述します。
タプルオブジェクトの定義の書式
変数名 =(値1, 値2, 値3, ・・・)
定義例
num_tuple =(10, 20, 30)
animal_tuple =(”象”, “虎”, “ネコ”, “キリン”)
リストは[]を使って定義をしますが、タプルは()を使って定義をします。
では、具体的にプログラムで示しましょう。次のように『タプル』を定義します。
# タプルオブジェクトの定義
num_tuple = (10, 20, 30)
animal_tuple = ("象", "虎", "ネコ", "キリン")
# タプル内容の画面表示
print(num_tuple)
print(animal_tuple)
『タプル』を参照する変数をprint関数の引数で指定すると、タプル内容の全てを表示することができます。
(10, 20, 30)
('象', '虎', 'ネコ', 'キリン')
タプルオブジェクトの構造は、次のようになっています。
このようにデータ構造自体は「リスト」と全く同じですね。複数の変数を内包し、オブジェクトを参照できる形になっています。
「タプル」はimmutable(変更不可)なオブジェクト
「タプル」と「リスト」のもっとも大きな違いは次のものです。
この違いによって扱えるメソッドには大きな違いが出てきます。
「リスト」には要素を追加・削除できるappendメソッドやpopメソッドがありますが、「タプル」にはありません。
それはオブジェクトが「mutable」なのか「immutable」であるかの違いなのです。
要素へのアクセスは、リストと同じように[]を利用します。()ではないことに注意しましょう。
# タプルオブジェクトの定義
num_tuple = (10, 20, 30)
# タプル要素の書き換え
num_tuple[0] = 50
immutableなタプルは、上記のように要素を書き換えようとするとエラーが発生します。
File "C:/PythonProject/project1/main.py", line 5, in <module>
num_tuple[0] = 50
TypeError: 'tuple' object does not support item assignment
これは、『タプル』が「immutableオブジェクト」だからこそなのです。
「タプル」と「リスト」の違いは、生成後にオブジェクトを変更できるかどうかの違いです。
タプルの要素数の取得方法
タプルの「要素数」はリストと同じで、len関数を使用すれば取得できます。
リストの要素数の取得方法
len(タプルオブジェクト)
len(タプルを参照する変数名)
使用例
num = len((10, 20, 30))
num = len(num_tuple)
実際のプログラムでは、len関数を次のように呼び出します。
# タプル変数の定義
num_tuple = (10, 20, 30)
animal_tuple = ("象", "虎", "ネコ", "キリン")
# タプル要素数の表示
print(len(num_tuple))
print(len(animal_tuple))
3
4
長さを調べることはオブジェクトを変更しないため、『リスト』でも『タプル』でも同じように利用できます。
「len」とは「length:長さ」のことです。この関数はあらかじめ用意されているので、いつでも呼び出すことができます。
変更できない『タプル』オブジェクトを作る意味
『タプル』って一度作ったら変えられないんですか。ふんふん・・・。
えっ?変更できない『タプル』ってなんの意味があるんですか?値を変えられなかったら何もできないってことじゃないですかっ!?
それはね、視点を狭めすぎだね。「値を変えられないことは意味がない」ってことではないんだよ。
確かに、プログラムは値を移り変えながら処理するのが基本だけど、変わりたくない値だってあるんだよ。
値が変更できないことはデメリットなのか?
値を変えることができない『タプル』とは、プログラムで役に立たないのでしょうか?
No!
そんなことはありません。「変更できないという特性」を持っていると考えれば、それを活かす方法はあります。要は、この特性をどのように捉えるかなんです!
「変更できない」ということは、「変更されない」ことが強みとなりうるのです。
この「変更不可という特性」を活かすも殺すも、それを使うプログラマー次第です。道具の使い方を考えられる、そんな考え方を持つプログラマーは優秀です。
タプルを使ったプログラム例
氏名や誕生日といったデータは、通常は変化することがない情報ですね。
例えば、次のようにタプルで定義することで、誤って変更されることのないデータとして管理することができます。
# タプル定義
member = (
("坂本龍馬", "さかもとりょうま", 1836, 1, 3,),
("勝海舟", "かつかいしゅう", 1823, 3, 12),
("西郷隆盛", "さいごうたかもり", 1828, 1, 23),
)
# タプル要素を順にフォーマットで表示
for m in member:
print("氏名:", m[0], m[1], m[2], "年", m[3], "月", m[4], "日")
氏名: 坂本龍馬 さかもとりょうま 1836 年 1 月 3 日
氏名: 勝海舟 かつかいしゅう 1823 年 3 月 12 日
氏名: 西郷隆盛 さいごうたかもり 1828 年 1 月 23 日
扱いたいデータをどのような性質のデータとして管理したいか?
これを決めるのは皆さんであり、『リスト』か『タプル』か、また別のコンテナなのかを選択できる技術が必要です。
「タプル」と「リスト」を相互変換する方法
ほーい。『タプル』と『リスト』は兄弟のように近い関係だけど、変更できる・できないという特性が違うんですね。
でもでも、『タプル』で管理しているデータを、変更したくなっちゃったらどうしたらいいんですか?無理ですよねー・・・。
『タプル』自体を変更することはできないね。それができちゃったら『タプル』じゃないからね。
『リスト』と『タプル』が近い関係性を利用すれば、近いことはできるよ!
変更できる『リスト』と変更できない『タプル』、この2人の兄弟は相互に相手を作り出すことができます。
タプルからリストオブジェクトの作成方法
『タプル』から『リスト』を作り出すにはlist関数を使います。引数にタプルオブジェクトを指定すれば同じ要素の『リスト』を作り出すことができます。
# タプルオブジェクトの定義
tuple1 = (10, 20, 30)
# タプルからリストオブジェクトを生成
list1 = list(tuple1)
print("tuple:", tuple1)
print("list :", list1)
tuple: (10, 20, 30)
list : [10, 20, 30]
リストからタプルオブジェクトの作成方法
今度は逆に『リスト』から『タプル』を作り出すにはtuple関数を使います。引数にリストオブジェクトを指定すれば同じ要素の『タプル』を作り出すことができます。
# リストオブジェクトの定義
list1 = [10, 20, 30]
# リストからタプルオブジェクトを生成
tuple1 = tuple(list1)
print("list :", list1)
print("tuple:", tuple1)
list : [10, 20, 30]
tuple: (10, 20, 30)
Q&A:Pythonの「タプル」に関するよくある質問
「タプル」で何か質問ある人はどうぞ!
Q:『タプル』と『リスト』は一緒に使えるの?
はい、はーい。質問です。『リスト』と『タプル』はものすごくそっくりな兄弟みたいですね。この2人を一緒に使うことはできるのですか?
つまり、『リスト』の中に『タプル』を入れることなんてできるのですか?
はい、もちろんできますよ。プログラム例を使って説明しましょう!
次のプログラムは、『リスト』の中に『タプル』を要素として持つデータです。
# リストの中にタプルを定義
member = [
("坂本龍馬", "さかもとりょうま", 1836, 1, 3,),
("勝海舟", "かつかいしゅう", 1823, 3, 12),
("西郷隆盛", "さいごうたかもり", 1828, 1, 23),
]
print("追加前:", member)
# リスト要素にタプルを追加
member.append(("大久保利通", "おおくぼとしみち", 1830, 9, 26))
print("追加後:", member)
追加前: [('坂本龍馬', 'さかもとりょうま', 1836, 1, 3), ('勝海舟', 'かつかいしゅう', 1823, 3, 12), ('西郷隆盛', 'さいごうたかもり', 1828, 1, 23)]
追加後: [('坂本龍馬', 'さかもとりょうま', 1836, 1, 3), ('勝海舟', 'かつかいしゅう', 1823, 3, 12), ('西郷隆盛', 'さいごうたかもり', 1828, 1, 23), ('大久保利通', 'おおくぼとしみち', 1830, 9, 26)]
このようにすることで、人物の氏名や誕生日は変えることができないが、新しい人物はリストとして追加できるといったデータ構造を作り出すことができます。
Pythonはオブジェクトを組み合わせることで様々なデータ構造を作り出すことができます。
Q:『リスト』と『タプル』はオブジェクトとしての扱いはどう違うの?
ほーい。質問です。『リスト』と『タプル』はプログラムの中でオブジェクトとしての管理方法は違うのでしょうか?
Pythonってオブジェクトが別のものだったり、実は同じものだったりすることがありますよね?
そうですね。後から変更できる『リスト』と、変更できない『タプル』ではオブジェクトとしての管理方法がやっぱり違うんですね。
Pythonもできる限り無駄なオブジェクトを作らないように、不要なオブジェクトは効率よく管理する仕組みが備わっています。
『リスト』と『タプル』がいったいどのようにオブジェクトとして管理されているかを、オブジェクトIDを使って確認してみましょう。
リストは、次のようなプログラムでは2つのオブジェクトが生成されることになります。
# 同一内容のリストを変数に設定
list1 = [10, 20, 30]
list2 = [10, 20, 30]
print("list1 ID:", id(list1))
print("list2 ID:", id(list2))
list1 ID: 2565586838024
list2 ID: 2565586838088
このように同一のリスト内容であっても、異なる変数に代入した際には別のリストオブジェクトとして生成されます。
これは、「list1」と「list2」の各変数からリスト要素を変更した際に、お互いが影響しないように別のオブジェクトとして管理する必要があるためです。
では、タプルの場合はどうでしょうか?
# 同一内容のタプルを変数に設定
tuple1 = (10, 20, 30)
tuple2 = (10, 20, 30)
print("tuple1 ID:", id(tuple1))
print("tuple2 ID:", id(tuple2))
tuple1 ID: 2565600691544
tuple2 ID: 2565600691544
タプルの場合は1つのタプルオブジェクトしか生成されず、2つの変数が共に同じタプルオブジェクトを参照しています。
これは、タプルオブジェクトが変更されることがない「immutable」であるため、同じタプルを参照していても問題がないためです。
こんな風にPythonも情報を、効率よく無駄なく管理するようになっています。
C言語技術者が知るべきPython言語との違い:「タプル」
すでにC言語を習得している人は、次のポイントに気を付けよう!
変更ができない『タプル』とは、C言語における「const」を利用した定数定義に相当する機能です。
定数化することで不用意な変更を防ぐことができる、それが「const」のメリットです。
C言語
// 定数テーブルの定義
const int tuple[] = {10, 20, 30};
printf("%d", tuple[0]);
Python
# タプルの定義
tuple = (10, 20, 30)
print(tuple[0])
C言語において「const」使うシーンを思い浮かべて、Pythonではタプルを使うとよいでしょう。
C言語の「const」は『C言語 constの利用価値【変数を定数化する方法と利用シーン】』の記事をご覧ください。
表現方法は違いますが、プログラミングの要素として「定数」という考え方は必要なものであるということです。