[Python入門]タプル:Python入門(3/3 ページ)
リストとよく似ているが、変更不可能という大きな特徴を持つ「タプル」の基本、その操作、リストとの違いなどについて説明する。
タプルの要素は変更不可能
既に述べたように、タプルの要素は変更できない。
mytuple = 1, 2, 3
mytuple[0] = 101 # エラー
ただし、このことには幾つかの注意点がある。まず、ある変数にタプルを代入した場合、「その変数に別のタプルを代入する」ことは可能な点だ。
mytuple = 1, 2, 3
mytuple = 4, 5, 6 # エラーではない
実行結果を以下に示す。
なぜこれが問題ないかというと、タプルは変更不可能(イミュータブル)だが、今述べた操作は、もともとのタプルから別のタプルへと「名札を付け替える」だけのことだからだ。
もう一つ。タプルの要素がリストのように変更可能なものの場合には、「タプルの要素の要素」は変更できる点だ。
mylist1 = [0, 1, 2]
mylist2 = [3, 4, 5]
mytuple = mylist1, mylist2
print(mytuple)
mytuple[0][0] = 100
print(mytuple)
mytuple[0] = [6, 7, 8] # エラー
実行結果を以下に示す。
上のコード例では、リストを要素とするタプルを作成して、その最初の要素であるリストの最初の要素を変更している。これはエラーとはならない。タプルの要素は変更できないが、その要素が変更可能な場合には、その変更までは制限されない。もちろん最後の行のようにタプルの要素を変更しようとするとエラーになる。
タプルの操作
その要素を変更できないことから、タプルに対して可能な操作はリストのそれと比べて少ないものになる。既に見た通り、インデックスやスライスによる要素の取り出しは可能だが、それに新しい値を代入することはできない。以下にタプルに対して可能な操作をまとめる(以下の表の「例」では、変数mytupleに「('shinji', 'kawasaki', 80)」というタプルを代入しているものとする)。
操作 | 方法 | 例 |
---|---|---|
タプルの要素数を求める | len(タプル) | len(mytuple)→3 |
タプルの要素から最大のものを求める | max(タプル) | max((1, 2, 3))→3 タプルの全要素が比較可能な場合のみ(文字列と数値は比較できないのでmax(mytuple)はエラーとなる) |
タプルの要素から最小のものを求める | min(タプル) | min((1, 2, 3))→1 タプルの全要素が比較可能な場合のみ(文字列と数値は比較できないのでmin(mytuple)はエラーとなる) |
タプルを結合する | タプル1 + タプル2 | mytuple + mytuple→('shinji', 'kawasaki', 80, 'shinji', 'kawasaki', 80) タプル1とタプル2を結合した新たなタプルが作成される |
タプルの繰り返し | タプル * n n * タプル |
mytuple * 2→('shinji', 'kawasaki', 80, 'shinji', 'kawasaki', 80) タプルをn回繰り返した新しいタプルが作成される |
タプルに要素itemが含まれているかどうかを調べる | item in タプル | 'isshiki' in mytuple→False |
タプルに要素itemが含まれていないかどうかを調べる | item not in タプル | 'isshiki' not in mytuple→True |
タプルに要素itemが含まれている場合にそのインデックスを得る | タプル.index(item) | mytuple.index(80)→2 |
要素itemがタプルに何個含まれているかを調べる | タプル.count(item) | mytuple.count('isshiki')→0 |
タプルの要素を並べ替える | sorted(タプル) | sorted((4, 1, 2, 6))→[1, 2, 4, 6] タプルはイミュータブルなので自身を破壊するsortメソッドはない。また、sorted関数にタプルを渡すと、その要素を並べ替えた新しい「リスト」が返される。タプルの全要素が比較可能でない場合はエラー(例外)が発生する |
タプルの要素を反転する | reversed(タプル) | reversed(mytuple)→80、'kawasaki'、'shinji'の順に値を返すイテレータ タプルはイミュータブルなので自身を破壊するreverseメソッドはない。reversed関数にタプルを渡すと、その要素を逆順に並べ替えた「イテレータ」が返される |
タプルの操作 |
リストとタプルの違いはあるが、上に示した操作は両者に共通に行える。それぞれの操作の詳細については第17回「リストの操作」を参照してほしい。
タプルとリストの違い
変更可能と変更不可能という違いはあるが、リストとタプルはよく似ている。任意の型のデータを、任意の数だけ格納できる。角かっこ「[]」にインデックスを指定して、あるいはスライスを行って、格納されている要素を取り出せる。だが、実際の使われ方にはそれぞれに特徴がある。
Python公式サイトのFAQには「なぜタプルとリストという別のデータ型が用意されているのですか?」という項目がある。詳しくはこちらを参照してほしいのだが、簡単にまとめると、リストは「同種のデータを複数個並べて管理する」ことを主たる目的としている。一方、タプルは「異なる種類だが(あるいは同じ種類で)、関連性のあるデータをひとまとめにする」ために使われる。
例えば、前回に紹介したenumerate関数は、「リストの要素とインデックス」をタプルにまとめて返送するイテレータを戻り値とする関数だった。このように関連する複数のデータを「1個のデータ」として扱う際には、タプルを利用するのが一般的だ。自分で作成する関数で複数の値を返したいというときにもタプルを使えば、簡単にそれを実現できる。
また、「名前」「名字」「体重」……といったデータを簡易的にまとめるのにもタプルは便利だ。本稿の冒頭では次のようなサンプルコードを示した。
sk = ('shinji', 'kawasaki', 80)
print(sk)
このコードを変更して、2人分の名前と名字と体重を扱ってみよう。
sk = ('shinji', 'kawasaki', 80)
mi = ('masahiko', 'isshiki', 65)
person_list = [mi, sk]
for person in person_list:
print(f'{person[1]}さんの体重は{person[2]}kgです')
実行結果を以下に示す。
このコードでは一人一人のデータをタプルにまとめて、それをリストで管理している。タプルの要素は文字列と整数値だが、特定の個人を表現するひとまとまりのデータとなっている。これに対して、リストは今述べた「特定の個人を表現する同種のデータ」を格納するためのものとなっている。
もちろん、タプルもリストも任意の型のデータを好きなだけ格納できるので、上のコードでタプルとリストの役割を逆にしてもコード的には成立するし、実際にプログラムを書く際にどのような使い方をするかは時と場合によるだろう。だが、基本的な考え方としては今述べたような使い方が前提とされていることは覚えておこう。
さらに変更可能と変更不可能という両者の性質の違いから生まれる、使い方の違いもあるが、これについては次回見ていくことにする。
なお、「この値は名前を表し、この値は名字を……」のようなデータが必要であれば、次回に紹介する辞書を使うのがよい。
まとめ
今回のまとめ:タプル
- タプルはかっこで囲んで表現される
- タプルを作成するには、その要素をカンマ区切りで並べる(それらをかっこで囲んでもよい)
- 1つの要素だけで構成されるタプルを作成するには、その要素に続けてカンマ(,)を置く
- タプルの要素を取り出すには「[インデックス]」を付加する
- タプルの要素は変更できない
- 複数のデータからタプルを作成することを「パック」と呼ぶ
- タプルの要素を個別の変数へ代入できる。これを「アンパック」と呼ぶ
- タプルの要素をアンパックするときには、要素の数とアンパック先の変数の数が同じである必要がある
- タプルの要素は変更できないが、タプルにリストなど変更可能なオブジェクトを格納している場合、タプルの要素の要素は変更できる
- タプルは関連性のあるデータをひとまとめに扱うために使う
- リストは同種のデータを複数格納して扱うために使う
「Python入門」
Copyright© Digital Advantage Corp. All Rights Reserved.