検索
連載

[解決!Python]タプルの要素を取り出すには解決!Python

Pythonでタプルの要素を取り出すにはインデックスやスライスを使う方法と要素のアンパックを使う方法がある。これらを紹介する。

PC用表示 関連情報
Share
Tweet
LINE
Hatena
「解決!Python」のインデックス

連載目次

# アンパック
mytuple = (0, 1, 2)
x, y, z = mytuple
print(x, y, z)  # 0 1 2

# インデックスによるアクセス
mytuple = tuple(range(10))
print(mytuple)  # (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

n = mytuple[2# 正数はタプル先頭からのインデックスを表す
print(n)  # 2
n = mytuple[-3# 負数はタプル末尾からのインデックスを表す
print(n)  # 7

# スライスによるアクセス
s = mytuple[0:5# タプルの0〜4番目の要素
print(s)  # (0, 1, 2, 3, 4)
s = mytuple[2:]  # 2番目以降の全要素
print(s)  # (2, 3, 4, 5, 6, 7, 8, 9)
s = mytuple[:5# タプルの0〜4番目の要素
print(s)  # (0, 1, 2, 3, 4)
s = mytuple[:]  # タプルの全要素
print(s)  # (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
s = mytuple[::2# 0、0+1×2=2、0+2×2=4、……の要素(偶数インデックス)
print(s)  # (0, 2, 4, 6, 8)
s = mytuple[0:5:2# 0、0+1×2=2、0+2×2=4がインデックスの要素
print(s)  # (0, 2, 4)

#  スライスに負数を指定した場合
s = mytuple[-1:]  # 末尾要素のみで構成されるタプル
print(s)  # (9,)
s = mytuple[-5:-2# s = mytuple[5:8]と同じ
print(s)  # (5, 6, 7)
s = mytuple[::-1# 全要素を逆順に並べたタプル
print(s)  # (9, 8, 7, 6, 5, 4, 3, 2, 1, 0)


タプルの要素のアンパック

 タプルはリストとは異なり、その要素を変更できない。そのため、タプルに対して行えるのは、主にその要素の取り出しとなる。タプルから要素を取り出すには、インデックスを使って個別の要素を指定するか、スライスを使って特定範囲の要素群を指定するか、要素をアンパックするかとなる。

 一番簡単なのは要素をアンパックすることだ。ここでいうアンパック(アンパック代入)とはタプル(やリスト、集合、辞書など)に含まれる個々の要素を別の変数へ代入する操作のことだ。これには代入先の変数の数とタプルの要素数が一致する必要がある。

 以下に例を示す。

mytuple = (0, 1, 2)
x, y, z = mytuple
print(x, y, z)  # 0 1 2


 この例ではmytupleには0、1、2の3つの要素を持つタプルが代入されている。2行目でタプルのアンパック代入を行っている。タプルは3つの要素で構成されているので、代入先の変数もそれに合わせて3つ用意してある。変数の数と要素の数が一致しない場合には「too many values to unpack」「not enough values to unpack」などのメッセージとともにValueError例外が発生する。

インデックスを使ったタプルの要素の取り出し

 インデックスを使ってタプルの要素を取り出すには、角かっこ「[]」に取り出したい要素のインデックスを指定する。

 以下に例を示す。

mytuple = tuple(range(10))
print(mytuple)  # (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

n = mytuple[2# 正数はタプル先頭からのインデックスを表す
print(n)  # 2
n = mytuple[-3# 負数はタプル末尾からのインデックスを表す
print(n)  # 7


 正の整数をインデックスに指定した場合は、タプルの先頭からのインデックスを表す。タプルの先頭要素のインデックスは0となることには注意すること。よって、0が先頭の要素を表し、1がその次の要素を表し、……となる。上の例では、タプルには0〜9の10個の要素が含まれているのでインデックス0はその先頭要素である「0」を、インデックス2は3番目の要素である「2」を表す。

 負の整数を指定した場合は、タプル末尾からのインデックスとなる。−1が末尾の要素を表し、−2は末尾から2番目の要素を表し、……となる。上の例では、タプルには0〜9の10個の要素が含まれているのでインデックス−1はその末尾要素である「9」を、インデックス−3は末尾から3番目の要素である「7」を表す。

スライスを使ったタプルの要素の取り出し

 タプルやリストなど、要素をインデックスで指定可能なオブジェクトに対して、その要素の範囲を角かっこに続けて「タプル[lower_bound:upper_bound:stride]」のようにして、その範囲を指定することで、その範囲の要素を取り出せる。取り出したものや、このような範囲指定のことをスライスと呼ぶ。ここでlower_boundはスライスの開始位置を、upper_boundはスライスの終了位置を、strideはlower_boundとupper_boundに含まれる範囲のインデックスを計算する際の増分(または減分)を表す。

 lower_bound、upper_bound、strideは全て省略可能であり、省略時にはlower_boundには0が指定されたものとして、upper_boundにはタプルの長さ(len(タプル))が指定されたものとして扱われる(strideに正数を指定した場合。strideに負数を指定すると、lower_boundがタプル末尾を、upper_boundがタプル先頭を指すようになる)。strideが省略されたときには「1」が指定されたものとして扱われる。

 lower_boundとupper_boundは「タプル[lower_bound]」「タプル[upper_bound]」のようにインデックス指定したタプルの要素と同じものを表す。「タプル[lower_bound:upper_bound]」と開始位置と終了位置を指定したとき、上でも述べたようにlower_boundはスライスの開始位置の要素を、upper_boundは終了位置の要素を表すが、実際にはupper_boundで指定される要素が取り出されることはない。つまり、「タプル[0:5]」はタプルの0、1、2、3、4番目の要素を取り出すことになる(上述したようにstrideを省略したときには「1」が指定されたものとして扱われるので、これは「タプル[0:5:1]」と指定したとの同じ)。

 以下に例を示す。

mytuple = tuple(range(10))
print(mytuple)  # (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

s = mytuple[0:5# タプルの0〜4番目の要素
print(s)  # (0, 1, 2, 3, 4)


 upper_bound(終了位置)を指定した場合には、タプルの末尾要素までスライスに含まれる。以下に例を示す。

s = mytuple[2:]  # 2番目以降の全要素
print(s)  # (2, 3, 4, 5, 6, 7, 8, 9)


 lower_bound(開始位置)を指定した場合には、タプルの先頭要素を示すインデックス0が指定されたものとして扱われる。以下に例を示す。

s = mytuple[:5# タプルの0〜4番目の要素
print(s)  # (0, 1, 2, 3, 4)


 lower_boundとupper_bound(とstride)を省略したときには、タプルの全要素がスライスに含まれる。以下に例を示す。

s = mytuple[:]  # タプルの全要素
print(s)  # (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)


 stride(増分)を指定した場合には、lower_bound ≦ idx < upper_boundの範囲に含まれるidxが「idx=lower_bound+stride×n」という式で計算されて(nは0以上の整数)、そのidxに対応する要素が、取り出されるスライスの要素となる。以下に例を示す。

s = mytuple[::2# 0、0+1×2=2、0+2×2=4、……の要素(偶数インデックス)
print(s)  # (0, 2, 4, 6, 8)


 この例では、lower_boundとupper_boundが省略されているが、strideが「2」と指定されている。そのため、lower_boundとupper_boundの間で「idx=0+n×2」(nは0以上の整数)で計算されるインデックスに対応する要素が取り出される(idxがlower_boundとupper_boundの範囲外になったところで計算は終了する)。この範囲に含まれるidxは0、2、4、6、8となるのでこれらのインデックスに対応する要素である0、2、4、6、8が取り出される。

 以下はlower_boundとupper_boundを指定したものだ。lower_boundには0が、upper_boundには5が指定されているので、インデックス0、2、4に対応する要素が取り出されている。

s = mytuple[0:5:2# 0、0+1×2=2、0+2×2=4がインデックスの要素
print(s)  # (0, 2, 4)


スライスに負数を指定した場合

 スライスに負の整数を指定した場合は、インデックスに負数を指定した場合と同様、タプル末尾からのインデックスが指定されたものとして扱われる。注意が必要なのは、lower_bound、upper_bound、strideを省略した場合、それらはそれぞれ0、タプルの長さ、1を指定されたものとして扱われる点だ。

 つまり、末尾から先頭の要素を取り出すつもりで以下のようなコードを書いても、それは想定とは意味が異なり、末尾の要素から末尾の要素+1の範囲に含まれる要素を取り出すことになる(つまり、末尾要素のみを要素とするタプルとなる)。

s = mytuple[-1:]  # 末尾要素のみで構成されるタプル
print(s)  # (9,)


 以下の例も同様だ。ここではlower_boundに「-5」を、upper_boundに「-2」を指定しているが、これはlower_boundに「5」を、upper_boundに「8」を指定したのと同じ結果になる。「-5」は末尾から5つ目の要素を意味するもので、末尾から5つ目とはインデックスで表すと9→8→7→6→5、すなわちインデックス5を表しているからだ(「-2」も同様)。

s = mytuple[-5:-2# s = mytuple[5:8]と同じ
print(s)  # (5, 6, 7)


 そのため、lower_boundとupper_boundの値を逆にすると、要素が存在しなくなり、空のタプルが得られる。

s = mytuple[-2:-5# s = mytuple[8:5]と同じ
print(s)  # ()


 これは「lower_bound ≦ idx < upper_bound」すなわち「8 ≦ idx < 5」の範囲に含まれるidxが存在しないからだ。

 stride(増分)に負値を与えると、範囲の計算が切り替わり「5 < idx ≦ 8」の範囲に含まれるインデックスに対応する要素が得られる。

s = mytuple[-2:-5:-1# s = mytuple[8:5:-1]と同じ
print(s)  # (8, 7, 6)


 ただし、stride(増分)が-1なので、要素が取り出されるのは8、7、6と逆順になっている点に注意すること。

 また、lower_boundまたはupper_boundの指定を省略して、strideに負値を指定した場合には、省略したlower_boundはタプルの末尾を、upper_boundはタプルの先頭を表すように調整される。

 以下に例を示す。

s = mytuple[::-1# 全要素を逆順に並べたタプル
print(s)  # (9, 8, 7, 6, 5, 4, 3, 2, 1, 0)


 この例では、lower_boundとupper_boundの両方が省略し、strideに負値を指定しているので、タプルの末尾から先頭へと向かって、要素が順に取り出されている。

「解決!Python」のインデックス

解決!Python

Copyright© Digital Advantage Corp. All Rights Reserved.

[an error occurred while processing this directive]
ページトップに戻る