Python独習塾

  • ホーム
  • Pythonのtuple(タプル)の解説【イミュータブル、シーケンス】

Pythonのtuple(タプル)の解説【イミュータブル、シーケンス】

  • 作成日: 2025-07-06
  • 更新日: 2025-07-07
  • カテゴリ: 基本
  • タグ: tuple

この記事ではPythonのtupleの取り出し方、追加、リストへの変換、要素数の取得、リストとの違い、tuple関数、結合、展開、比較、for文での回し方を解説していきます
参考ドキュメントは以下になります。

出典:5. タプルとシーケンス — データ構造 — Python 3.13.5 ドキュメント

Pythonのtupleとは何ですか?

Pythonのtuple(タプル)はシーケンス型の1つです。複数の値をまとめたいときに使われます。イミュータブル(不変)なシーケンスで、値を変更できないのが特徴です。タプルはリストに非常によく似たデータ型です。

出典:5. タプルとシーケンス — データ構造 — Python 3.13.5 ドキュメント

tup = 1, 2, 3  # タプル。  

print(type(tup))  # <class 'tuple'>  
print(tup)  # (1, 2, 3)  

try:  
    # 値を変更しようとするとTypeErrorになる。  
    tup[0] = 100  
except ValueError as e:  
    print(e)  
    # TypeError: 'tuple' object does not support item assignment  

タプルの作り方は、上記のように1, 2, 3という感じで値をカンマで区切って、それを変数に代入します。あるいは(1, 2, 3)のようにカッコの中に値を区切ることでもタプルを作ることができます。

タプルはイミュータブル(不変)という特徴があり、そのため、変更したくない値を作りたい場合に使われます。リストなどはミュータブル(可変)です。

Pythonのtupleから要素を取り出したいんだけど?

Pythonのtupleから要素を取り出すには、角かっこを使ったインデックスアクセスを使います。

出典:5. タプルとシーケンス — データ構造 — Python 3.13.5 ドキュメント

# 文法  
variable = tuple[index]  
tup = (1, 2, 3)  

elem0 = tup[0]  # 0番目の要素を取り出す  
print(elem0)  # 1  

elem1 = tup[1]  # 1番目の要素を取り出す  
print(elem1)  # 2  

elem2 = tup[2]  # 2番目の要素を取り出す  
print(elem2)  # 3  

上記のようにtup[0]tupの0番目の要素を取り出せます。角かっこの中の添え字を変えると、その添え字(インデックス)に対応した要素を取り出すことができます。
添え字が範囲外、つまりタプルの要素数の範囲外になるとIndexErrorになります。

tup = (1, 2, 3)  

try:  
    tup[100]  
except IndexError as e:  
    print(e)  
    # tuple index out of range  

Pythonのtupleに要素を追加するには?

Pythonのtupleに要素を追加するには+=演算子を使います。

出典:5. タプルとシーケンス — データ構造 — Python 3.13.5 ドキュメント

tup = (1, 2, 3)  

tup += (4, )  # 末尾に4を追加  
print(tup)  # (1, 2, 3, 4)  

tup += (5, 6)  # 末尾に5, 6を追加  
print(tup)  # (1, 2, 3, 4, 5, 6)  

Pythonのタプルはイミュータブル(不変)ということでしたが、この動作はなぜ可能なのでしょうか?
Pythonの+=はインプレース演算を行います。

出典:インプレース (in-place) 演算子 — operator --- 関数形式の標準演算子 — Python 3.7.17 ドキュメント

インプレース演算では代入先のオブジェクトを新しいオブジェクトに書き換える動作をします。

tup = (1, 2, 3)  

print(id(tup))  # 1793809616512  
print(tup)  # (1, 2, 3)  

tup += (4, )  # インプレース演算でtupを書き換える  

print(id(tup))  # 1793809526800(識別値が変わってる)  
print(tup)  # (1, 2, 3, 4)  

id関数はオブジェクトの識別値を取得します。これはCPythonではメモリのアドレス値になっています。

出典:id関数 — 組み込み関数 — Python 3.13.5 ドキュメント

+=演算をするとtupが新しいオブジェクトに置き換えられます。つまり+=tupを直接書き換えているのではなく、新しいタプルを生成してそれをtupに置き換えているだけだということになります。
ということはタプルがイミュータブル(不変)であることは変わりはなく、起こっているのは単純に変数の置き換えだけ、ということです。

またタプルは足し算で演算できます。足し算の結果は新しいタプルです。

tup = (1, 2)  
tup2 = tup + (3, )  
tup3 = tup + (4, 5)  
print(tup2)  # (1, 2, 3)  
print(tup3)  # (1, 2, 4, 5)  

Pythonのtupleをlistに変換するには?

Pythonのtuple(タプル)をlist(リスト)に変換するには、タプルをlist()に渡します。

出典:5. タプルとシーケンス — データ構造 — Python 3.13.5 ドキュメント

関連記事:Pythonのリスト(list)の解説【append, extend】

tup = (1, 2, 3)  
lis = list(tup)  

print(lis)  # [1, 2, 3]  

また、リストをtuple()に渡すと、リストをタプルに変換することもできます。

lis = [1, 2, 3]  
tup = tuple(lis)  

print(tup)  # (1, 2, 3)  

Pythonのtupleの要素数(長さ)を得るには?

Pythonのtupleの要素数を得るにはlen関数を使います。

出典:len関数 — 組み込み関数 — Python 3.13.5 ドキュメント

tup = (1, 2, 3)  

print(len(tup))  # 3  

len()にタプルの変数を渡すと、そのタプルの長さを得ることができます。

Pythonのtupleとlistの違いはなんなの?

Pythonのtupleとlistの違いは、tupleはイミュータブル(不変)でlistはミュータブル(可変)ということになります。

出典:5. リスト型についてもう少し — データ構造 — Python 3.13.5 ドキュメント
出典:5. タプルとシーケンス — データ構造 — Python 3.13.5 ドキュメント

リストは可変なので、後から要素を変更できます。

lis = [1, 2, 3]  

lis[0] = 10  
print(lis)  # [10, 2, 3]  

タプルは不変なので、後から要素を変更できません。

tup = (1, 2, 3)  

try:  
    # 変更しようとするとTypeErrorになる。  
    tup[0] = 10  
except TypeError as e:  
    print(e)  
    # 'tuple' object does not support item assignment  

タプルを変更するには新しく変数を置き換える必要があります。

tup = (1, 2, 3)  

tup = (4, 5, 6)  
print(tup)  # (4, 5, 6)  

リストは可変なので要素を追加するメソッド、appendなどがあります。

関連記事:Pythonのリスト(list)の解説【append, extend】

lis = [1, 2, 3]  

lis.append(4)  
print(lis)  # [1, 2, 3, 4]  

タプルは不変なので要素を追加するメソッドはありません。もっとも+=演算子で要素を追加(したように見せる)することはできます。

tup = (1, 2, 3)  

tup += (4, )  
print(tup)  # (1, 2, 3, 4)  

Pythonのtuple関数とはなんなの?

Pythonのtuple関数はtupleを生成する組み込み関数です。

出典:tuple関数 — 組み込み関数 — Python 3.13.5 ドキュメント

tuple関数は関数と呼ばれていますが、実体はクラスです。

print(tuple)  # <class 'tuple'>  

tuple関数はタプルを生成したいときに使います。

tup = tuple()  

print(tup)  # ()  

また、tuple関数にはリストやrangeなどのシーケンス型を渡すことができます。
tuple()にリストを渡すとタプルに変換され、rangeを渡すと数列を含んだタプルが生成されます。

関連記事:Pythonのrangeの解説【for文,1から,逆順】

tup = tuple([1, 2, 3])  
print(tup)  # (1, 2, 3)  

tup = tuple(range(4))  
print(tup)  # (0, 1, 2, 3)  

集合もtuple関数に渡すことができます。

tup = tuple({1, 2, 3})  
print(tup)  # (1, 2, 3)  

辞書のkeysvalues, itemsなどもtuple関数に渡すことができます。

d = {'a': 1, 'b': 2, 'c': 3}  

print(tuple(d.keys()))  # ('a', 'b', 'c')  
print(tuple(d.values()))  # (1, 2, 3)  
print(tuple(d.items()))  # (('a', 1), ('b', 2), ('c', 3))  

zipオブジェクトもtuple関数に渡すことができます。

a = ('a', 'b', 'c')  
b = (1, 2, 3)  
tup = tuple(zip(a, b))  
print(tup)  # (('a', 1), ('b', 2), ('c', 3))  

enumerateオブジェクトもtuple関数に渡すことができます。

tup = tuple(enumerate([10, 20, 30]))  
print(tup)  # ((0, 10), (1, 20), (2, 30))  

Pythonのtupleで他のタプルと結合するには?

Pythonのtupleで他のタプルと結合するには+演算子か+=演算子を使います。

出典:5. タプルとシーケンス — データ構造 — Python 3.13.5 ドキュメント

+演算子でタプル同士を結合することができます。演算の結果は新しい結合されたタプルです。

tup1 = (1, 2)  
tup2 = (3, 4)  
tup3 = tup1 + tup2  
print(tup3)  # (1, 2, 3, 4)  

+=演算子でタプルに別のタプルを結合(連結)することができます。

tup1 = (1, 2)  
tup2 = (3, 4)  
tup1 += tup2  
print(tup1)  # (1, 2, 3, 4)  

+=演算子はインプレース演算で演算したオブジェクトを新しいオブジェクトに置き換えています。タプルはイミュータブル(不変)オブジェクトなので、タプル自体を直接変更しているわけではありません。

tup = (1, 2)  
print(id(tup))  # 2178802993024  
print(tup)  # (1, 2)  

tup += (3, 4)  
print(id(tup))  # 2178803052560  
print(tup)  # (1, 2, 3, 4)  

id関数はオブジェクトの識別値を返しますが、上記の場合だと+=演算前と演算後のtupの識別値が変わってるのがわかります。これは+=演算のインプレース演算でtup自体を新しいオブジェクトに置き換えているからです。

出典:インプレース (in-place) 演算子 — operator --- 関数形式の標準演算子 — Python 3.7.17 ドキュメント
出典:id関数 — 組み込み関数 — Python 3.13.5 ドキュメント

Pythonのtupleを展開するには?

Pythonのtuple(タプル)を展開するには=演算子を使います。

出典:5. タプルとシーケンス — データ構造 — Python 3.13.5 ドキュメント

a, b = 1, 2  # a, bに展開(アンパック)  

print(a, b)  # 1 2  
tup = (1, 2, 3)  
a, b, c = tup  # a, b, cに展開(アンパック)  

print(a, b, c)  # 1 2 3  

=演算子の右辺にタプルを配置し、左辺に変数を書きます。すると、各変数にタプルの要素が展開されます。展開はタプルの先頭から順に行われ、a, b, cにはそれぞれタプルの0番目、1番目、2番目の要素が展開されます。

Pythonのtuple同士を比較するには?

Pythonのtuple同士を比較するには==!=演算子を使います。

tup1 = (1, 2)  
tup2 = (1, 2)  
tup3 = (3, 4)  

print(tup1 == tup2)  # True  
print(tup1 != tup2)  # False  
print(tup1 == tup3)  # False  
print(tup1 != tup3)  # True  

上記の場合、tup1tup2は値的に同じものです。そのため==演算子ではTrueになり、!=演算子ではFalseになります。
tup2tup3は値的に違うものです。よって==演算子ではFalseになり、!=演算子ではTrueになります。

タプル同士の大小も比較できます。

tup1 = (1, 2)  
tup2 = (1, 3)  

print(tup1 < tup2)  # True  
print(tup1 <= tup2)  # True  
print(tup1 > tup2)  # False  
print(tup1 >= tup2)  # False  

Pythonのtupleでis演算子は値の比較にはならないの?

Pythonのis演算子は値の比較ではなくオブジェクトの識別値の比較です。

tup1 = (1, 2)  
tup2 = (1, 2)  

print(tup1 is tup1)  # True  
print(tup1 is tup2)  # False  

出典:演算子から関数への対応表 — operator --- 関数形式の標準演算子 — Python 3.13.5 ドキュメント

識別値とは、オブジェクトのメモリ上のアドレスのことです。どういうことかと言うと、メモリ上で同じオブジェクトならそれらは同じアドレスになります。メモリ上で違うオブジェクトなら違うアドレスになります。

CPythonの実装言語であるC言語ではmalloc関数などで動的にメモリを確保します。この関数は呼び出しごとに違うメモリアドレスを返します。

#include <stdio.h>  
#include <stdlib.h>  

int main(void) {  
    // int型のメモリを動的にp1に確保。  
    int *p1 = malloc(sizeof(int));  
    printf("p1の持っているアドレスは%p\n", p1);  
    // p1の持っているアドレスは0x5556292612a0  

    // int型のメモリを動的にp2に確保。  
    int *p2 = malloc(sizeof(int));  
    printf("p2の持っているアドレスは%p\n", p2);  
    // p2の持っているアドレスは0x5556292616d0  

    free(p1);  // メモリを解放  
    free(p2);  // メモリを解放  
    return 0;  
}  

CPythonでもmalloc系の関数が使われているので、オブジェクトは確保するごとにメモリのアドレスが変わります。これが違うオブジェクトで識別値が異なる理由です。

Pythonのtupleをfor文で回すには?

Pythonのtuple(タプル)はfor文で回せます。

関連記事:Pythonのfor文(繰り返し処理、ループ)を解説【range, enumerate】

tup = (1, 2, 3)  

for elem in tup:  
    print(elem)  
1  
2  
3  

回し方はリストなどと同じです。for文のinの右側にタプルを書いて、inの左側に変数を書きます。そうすると変数にタプルの要素が代入されていきます。

関連記事:Pythonのリスト(list)の解説【append, extend】

Pythonのtupleで内包表記をやるには?

Pythonにはtupleの内包表記はありません。カッコを使った表記はありますが、これはジェネレータ式と呼ばれるものです。

出典:6. ジェネレータ式 — 式 (expression) — Python 3.7.17 ドキュメント

g = (el for el in range(4))  
print(g)  
# <generator object <genexpr> at 0x7f13ad524e80>  

ジェネレータ式をtuple関数に渡せば、ジェネレータからタプルを生成できます。

tup = tuple((el for el in range(4)))  
print(tup)  # (0, 1, 2, 3)  

またはリスト内包表記をtupleに変換することもできます。

tup = tuple([el for el in range(4)])  
print(tup)  # (0, 1, 2, 3)  

ジェネレータ式とリスト内包表記、どちらの方が速いの?

ジェネレータ式とリスト内包表記を使う場合、どちらの方が速いのか。これはリスト内包表記の方が若干速いです。

import timeit  

# ジェネレータ式を使うバージョン  
def generator_version():  
    tuple((el for el in range(5000000)))  

# リスト内包表記を使うバージョン  
def list_version():  
    tuple([el for el in range(5000000)])  

# 時間を計測  
generator_time = timeit.timeit(generator_version, number=10)  
list_time = timeit.timeit(list_version, number=10)  

print(f"tupleとジェネレータ式: {generator_time:.4f} 秒 (10 回平均)")  
print(f"tupleとリスト内包表記: {list_time:.4f} 秒 (10 回平均)")  

上記の検証用コードを筆者の環境で実行すると以下のような結果になります。

tupleとジェネレータ式: 2.6318 秒 (10 回平均)  
tupleとリスト内包表記: 2.2989 秒 (10 回平均)  

リスト内包表記の方がジェネレータ式より13%ほど速い結果になりました。

カテゴリー