タプル

出典: フリー百科事典『ウィキペディア(Wikipedia)』

タプル (tuple, 「トゥープル」と発音されることもある)とは、2 つ組を表すダブル (double)、3 つ組を表すトリプル (triple) のような組を表す英単語を一般化した言葉から来ており、数学計算機科学などいくつかの分野で、通常順序づけられた対象の並びを表すために用いられる。 特に、n 個の組を英語では n-tuple と書き、日本語では通常 nと訳される。 タプルの概念そのものもと呼ばれる場合がある。

目次

[編集] 数学におけるタプル

[編集] 非形式的概説

集合論では n (n-tuple) とは n 個の対象 a1, a2, ..., an の順序づけられた組であり、普通、括弧でくくって (a1, a2, a3, ..., an) のように書かれる。 タプルが順序づけられているということは、2 つの n 組 (a1, a2, ..., an) と (b1, b2, ..., bn) が等しいとされるのが、対応する位置の要素がすべて等しいとき、すなわち (a1 = b1) ∧ (a2 = b2) ∧ ... ∧ (an = bn) であるとき、かつそのときに限ることを意味する。 タプルと直積集合には密接な関係があり、n 組の i 番目の対象が集合 Ai の要素とみなされるならば、n 組は直積集合 A1 × A2 × ... × An の要素である。

2 つの要素 aA, bB の順序づけられた組 (a, b) ∈ A × B は特に順序対 (ordered pair) と呼ばれる。 形式上は逆に、この順序対を元とすることによって一般の n 組 (n ≧ 2) を、例えば (a1, a2, a3, ..., an) = (...((a1, a2), a3), ..., an) のようにして構成的に定めることもできる。

タプルは様々な数学概念を定義するためにも利用される。 例えば、有限オートマトンは、入力アルファベットの有限集合 Σ, 状態の有限集合 S, 初期状態 s0S, 遷移関数 δ : Σ × SS, 受理状態の有限集合 FS の 5 つ組 (quintuple, 5-tuple) (Σ, S, s0, δ, F) として定められ、有向グラフは、頂点集合 V と辺の集合 AV × V の順序対 (V, A) として定められる。

なお数ベクトルも同じように要素の順序づけられた並びとして表されるが、数学の形式上、ある線形空間の要素とみなされるベクトル実数複素数など同じの要素からなるものである。 対して、タプルは任意の集合の要素を並べただけのずっと一般的な概念であるといえる。

[編集] 計算機科学におけるタプル

PythonMLHaskell といったいくつかのプログラミング言語は、このタプルを保持するデータ構造を有している。

[編集] プログラミング言語Pythonにおけるタプル

Pythonにおけるタプルとは、いくつかの値 (数値型、文字列型など)をひとつにまとめて、あたかもひとつの値のように扱う機能である。カッコで複数の値をまとめるという見た目が似ているのでよくリスト配列と混同されるが、タプルは目的が異なっており、リストや配列が同質の (同じ型をもつ) オブジェクトをまとめるのに対し、タプルは用途や型が異なるオブジェクトをひとつにまとめるために使われる。このためタプルの働きは、むしろC言語構造体に似ているといえる。構造体には通常異なる型や名前をもった値がまとめて格納される。これによって、本来ならばひとつの値しか扱えない箇所 (関数の返り値や、変数への代入、配列の各要素など) で複数の値を同時に扱うことが可能になる。Python のタプルはこの構造体を匿名にしたようなものと考えることができる。

たとえば ('A', 1) という 2つの要素 (文字列および整数) からなるタプルを考えてみよう。タプルは、ひとつの「かたまり」として変数に代入できる:

 x = ('A', 1)

また、タプルはリスト内の単一の要素として代入・追加・削除ができる。

 s = [('A', 1), ('C', 3), ('E', 9)]   # 「2要素のタプル」からなる 3要素のリスト
 s[0] = ('B', 2)                      # リストの最初の要素を変更する
 del s[0]                             # リストの最初の要素を削除する

さらに、タプルは関数の返り値として使うこともできる。これによって、複数の値を返す関数を実現することができる。

 def func():
   return ('A', 1)
 
 x = func()        # x には ('A', 1) が入る

C や Java のような言語では、上のような関数は構造体あるいはインスタンスオブジェクトを返すように設計しなければならない。しかしタプルを使えば、複数の値をまとめたオブジェクトをその場で作成して返すことができる。もっとも、Python ではリストもその場で作成できるため返り値として使うことができるが、タプルを使って値を返すことにより、「つねに決まった個数の値を返す」という意図を表すことができる。

タプルはリストと同様に、個々の要素を添え字によって参照できる。この機能が、よくリストと混同されるゆえんである。しかしタプルでは以下のような構文によって、個々の要素をそれぞれ別々の変数に“分解”することができる。

 def func():
   return ('A', 1)
 
 (p,q) = func()         # p には 'A' が、q には 1 が入る

しかし C の構造体とは違い、タプルはあくまで「ひとつの値」であるため、一度構築したら中の値を変更することができない。

 x = ('A', 1)
 x[0] = 'B'        # エラー

タプルの値を変更する場合は、一度分解してから再構築する必要がある。以下の例はタプルの 1番目の要素 ('A') を別の値 ('B') に変更しているが、実際には元のタプルの値が変更されるのではなく、('B', 1) というタプルが新しく生成されている:

 x = ('A', 1)
 (p,q) = x         # 分解
 x = ('B', q)      # タプルを再構築

Python のタプルが変更不能になっているのには理由がある。タプルは辞書型のキーとして使えるように、同一のものをまとめたタプルは必ず同一のハッシュをもつことが保証されている。たとえば、以下のようにして辞書オブジェクトを作成すると:

 k = ('A', 1)      # 辞書のキーを作成
 dic = { k: 5 }    # 辞書を作成

ここで dic[('A', 1)]5 を返すようになる。かりにタプルが変更可能だったと仮定すると、以下のような操作が可能になる:

 k[0] = 'B'        # 辞書中で使われているキーをあとから変更 (実際には不可能)

こうしてしまうと、dic[('A', 1)] を評価したユーザは 5 を得るべきなのか、それとも (指定したキーが辞書中に存在しないという) KeyError例外を受けとるべきなのかがはっきりしない。タプルを不変にしておけばこのような事態を避けることができる。

タプルを辞書のキーとして使うことで、Python では多次元の配列も擬似的に辞書を使って実現することができる:

 m = {}
 m[(1,2)] = 3
 m[(5,4)] = 6

[編集] 関係データベースにおけるタプル

詳細は「組 (データベース)」を参照

関係データベースの理論である関係モデルでは、タプル (組) とはある関係 (リレーション)表 (テーブル) として表したときの 1 つの行にあたり、形式的には、上述のタプルと同様に属性名を添字とした属性の型の直積集合の要素として表される。