2.

Python タプルの要素参照 完全ガイド(インデックス / スライス / 負のインデックス / アンパック / ネスト)

編集
この記事の要点
  • タプルの要素は tup[インデックス] で参照する。インデックスは 0 始まり
  • 負のインデックスtup[-1])で末尾から参照できる
  • スライス tup[start:stop:step] で部分タプルを取得
  • アンパック代入a, b, c = tup のように複数変数に同時代入できる
  • ネストしたタプルは tup[0][1] のように連続して添字を指定する

タプルの要素参照とは

Python のタプル(tuple)は順序付きの不変シーケンスで、リスト同様にインデックスを使って各要素にアクセスできます。インデックスは0 始まりです。

基本構文

tup = ("a", "b", 1.1)

print(tup[0])  # a
print(tup[1])  # b
print(tup[2])  # 1.1

負のインデックス(末尾から)

Python では負のインデックスを使うと末尾からカウントできます。tup[-1] は最後の要素です。

tup = ("a", "b", "c", "d", "e")

print(tup[-1])  # e
print(tup[-2])  # d
print(tup[-5])  # a (= tup[0])

スライス(部分タプル)

tup[start:stop:step]部分タプルを取得できます。start は含み、stop は含みません。

tup = (0, 1, 2, 3, 4, 5)

print(tup[1:4])    # (1, 2, 3)
print(tup[:3])     # (0, 1, 2)     start 省略 = 先頭
print(tup[3:])     # (3, 4, 5)     stop 省略 = 末尾
print(tup[::2])    # (0, 2, 4)     1 つ飛ばし
print(tup[::-1])   # (5, 4, 3, 2, 1, 0)  逆順

アンパック代入

タプルの要素を同時に複数の変数へ代入できます。Python らしい書き方です。

tup = ("Alice", 30, "Tokyo")

name, age, city = tup
print(name)  # Alice
print(age)   # 30
print(city)  # Tokyo

* で残りをまとめる

tup = (1, 2, 3, 4, 5)

first, *middle, last = tup
print(first)   # 1
print(middle)  # [2, 3, 4]
print(last)    # 5

ネストしたタプル

タプルの中にタプルが入っている場合は連続して添字を指定します。

tup = (
    ("Alice", 30),
    ("Bob",   25),
    ("Carol", 28),
)

print(tup[0])      # ('Alice', 30)
print(tup[0][0])   # Alice
print(tup[0][1])   # 30
print(tup[1][0])   # Bob

存在しないインデックス

範囲外のインデックスを指定すると IndexError が発生します。

tup = ("a", "b", "c")

print(tup[3])
# IndexError: tuple index out of range

事前に長さをチェックしたい場合は len() を使います。

tup = ("a", "b", "c")

if len(tup) > 3:
    print(tup[3])
else:
    print("index out of range")

タプルの長さ・要素検索

tup = (10, 20, 30, 20, 40)

print(len(tup))         # 5      要素数
print(tup.count(20))    # 2      20 の出現回数
print(tup.index(30))    # 2      最初に 30 が現れる位置
print(20 in tup)        # True   要素の存在チェック

ループでの参照

tup = ("a", "b", "c")

# 値のみ
for x in tup:
    print(x)

# インデックス付き
for i, x in enumerate(tup):
    print(i, x)
# 0 a
# 1 b
# 2 c

タプルとリストの違い(参照面)

項目タプルリスト
記法(a, b, c)[a, b, c]
要素の参照tup[i]list[i]
要素の変更不可(イミュータブル)
速度やや高速やや遅い
用途固定データ・複数戻り値可変データ

要素の参照はリストもタプルも同じ書き方ですが、代入による変更はタプルでは不可です。

tup = (1, 2, 3)
tup[0] = 10
# TypeError: 'tuple' object does not support item assignment

関数の戻り値としてのタプル

Python の関数は暗黙的にタプルを返すことで複数値を返すパターンが定番です。受け取り側はアンパックで個別変数に分解します。

def divmod_custom(a, b):
    return a // b, a % b   # タプル(商, 余り)を返す

q, r = divmod_custom(17, 5)
print(q, r)   # 3 2

# タプルのまま受け取りインデックス参照
result = divmod_custom(17, 5)
print(result[0], result[1])   # 3 2

イテラブルのアンパック

関数呼び出し時にタプルを*で展開して個別の引数に渡せます。

def add(a, b, c):
    return a + b + c

args = (1, 2, 3)
print(add(*args))   # 6

# 辞書を ** で展開も同様
kwargs = {"a": 1, "b": 2, "c": 3}
print(add(**kwargs))   # 6

名前付きタプル(NamedTuple)

インデックスではなく名前で要素を参照したい場合は collections.namedtuple または typing.NamedTuple を使います。読みやすさが大きく向上します。

from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
p = Point(10, 20)

print(p.x, p.y)   # 10 20
print(p[0], p[1]) # 10 20  (インデックスでもアクセス可)

# typing.NamedTuple 版(型ヒント付き)
from typing import NamedTuple

class User(NamedTuple):
    name: str
    age: int

u = User("Alice", 30)
print(u.name, u.age)

タプルのループ走査と zip

複数のタプルを並列に処理するには zip() が便利です。

names = ("Alice", "Bob", "Carol")
ages  = (30, 25, 28)

for name, age in zip(names, ages):
    print(f"{name} は {age} 歳")
# Alice は 30 歳
# Bob は 25 歳
# Carol は 28 歳

タプルを辞書のキーにする

タプルは不変(hashable)のため、辞書のキーや集合の要素として使えます(リストはこれが不可)。

# 座標をキーにする
grid = {}
grid[(0, 0)] = "start"
grid[(5, 3)] = "treasure"
grid[(9, 9)] = "goal"

print(grid[(5, 3)])   # treasure

# 集合の要素として
visited = {(0, 0), (1, 0), (1, 1)}
print((1, 0) in visited)   # True

FAQ

Q: タプルとリストの参照速度に差は?
A: 一般にタプルの方が僅かに高速ですが、CRUD 用途ならリスト、定数として持つならタプルという使い分けが普通です。

Q: 名前付きで参照したい
A: collections.namedtuple または typing.NamedTuple を使えば tup.name のようにアクセスできます。

Q: 要素を 1 つだけ持つタプル
A: (1,) のように末尾にカンマを付けます。(1) はただの括弧でくくった整数になります。

Q: スライスで取り出した結果はタプル?
A: はい。元のタプルの新しいタプルとして返ります。元のタプルは変化しません。

関連

  • タプル — 不変のシーケンス
  • リスト — 可変のシーケンス
  • スライス — シーケンスの部分取得
  • アンパック代入 — 複数変数同時代入
  • enumerate — インデックス付きループ
  • namedtuple / NamedTuple — 名前付きタプル
  • zip — 並列イテレート
編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. タプルの作成
  2. 要素の参照

最近更新/作成されたページ