タプルを作成することを、「複数の値を1つのタプルにまとめる」という意味で「タプルのパック」と呼ぶことがある。これに対して、タプルに格納されている要素の一つ一つを別々の変数へ代入することもできる。これを「アンパック」と呼ぶ。以下に例を示す。
mytuple = (1, 2) # タプルのパック
(x, y) = mytuple # タプルのアンパック
print(x, y)
実行結果を以下に示す。
1行目では、複数の整数値が「パック」されたタプルが、変数mytupleに代入される。そして、次の行ではその「アンパック」が行われている。これにより変数xとyには、それぞれmytuple[0]の値とmytuple[1]の値が代入される。「これは名前が付いていないタプルの要素を変更しているのでは?」と思う方もいらっしゃるかもしれないが、そうではない。これは代入後の変数xとyの値を要素とする新たなタプルを作成しているのである(「(x, y)」というタプルには名前がないということだ)。
タプルを囲むかっこ「()」は省略可能なので、これらは次のように書いてもよい。
mytuple = 1, 2 # タプルのパック
x, y = mytuple # タプルのアンパック
print(x, y)
このとき、タプルの要素数とアンパック先の変数の数が一致している必要がある。以下に例を示す。
mytuple = 1, 2, 3
x, y, z = mytuple
print(x, y, z)
x = mytuple
print(x)
x, y = mytuple
print(x, y)
この例では、3つの要素からなるタプルを「3つの変数」「1つの変数」「2つの変数」に代入している。最初の例はタプルの要素数と変数の数が同じなのでアンパックが行われる。次の例では単に、変数xと変数mytupleが同じタプルを参照するようになるだけだ。最後の例では、アンパック先の変数が2つしかないので、エラー(ValueError例外)が発生する。
もう1つ注意することがある。それは関数の引数にタプルを指定する場合だ。以下の例を考えてみよう(最後の2行はどちらもエラーとなるので、自分で最後の行の実行結果を確認する場合には、下から2行目のコードをコメントアウトする必要がある)。
def myfunc1(x):
print(x)
def myfunc2(x, y):
print(x, y)
myfunc1((1, 2))
myfunc2(1, 2)
myfunc1(1, 2)
myfunc2((1, 2))
ここではパラメーターを1つ持つmyfunc1関数と、パラメーターを2つ持つmyfunc2関数を定義して、それを何通りかの方法で呼び出している。最初のmyfunc1関数の呼び出しではタプルを1つ引数に指定している。myfunc1関数のパラメーターxは、これを1つのタプルとして受け取るために関数は問題なく実行される。次のmyfunc2関数の呼び出しでは、2つの整数値を引数に指定している。myfunc2関数のパラメーターは2つなのでこれも問題はない。
問題なのは、3番目のmyfunc1関数の呼び出しだ。これは引数が2つ指定したものであり、「タプルのかっこを省略したもの」とは解釈されない。そのため、エラーが発生する。最後のmyfunc2関数呼び出しではタプルを1つだけ渡しているので、これもエラーとなる。引数リストのカンマ「,」はタプルの作成を意味しないことに注意しよう。
なお、タプルの要素を全て展開して関数に渡すには、第13回「関数の引数」の「引数のアンパック(展開)」で紹介したように「*」を付ける。以下に例を示す(実行結果は省略)。
myfunc2(*(1, 2))
mytuple = 1, 2
myfunc2(*mytuple)
なお、ここではタプルのアンパックを紹介したが、実際にはタプルだけではなく、リストや文字列などインデックスを指定して要素にアクセス可能なオブジェクトならどれでもアンパックが可能だ(これらの「インデックスによるアクセスが可能」なオブジェクトのことを、Pythonでは「シーケンス型」のオブジェクトと呼ぶため、「シーケンスのアンパック」と呼ぶこともある)。
a, b, c = [1, 2, 3]
print(a, b, c)
a, b, c = 'str'
print(a, b, c)
Copyright© Digital Advantage Corp. All Rights Reserved.