# リスト list と
タプル tuple の違いってなに?

リストは変更できる。
タプルは変更できない。

# 1. 機能的な違い

# 1.1. 変更できない

リストは変更できるので、問題なくこれが実行できますが

lst = [0, 1, 2]
lst[0] = 3

タプルは変更できないので、変更しようとすると TypeError になります。

tpl = (0, 1 , 2)
tpl[0] = 3  # TypeError
>>> tpl[0] = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> 

「変更できない」と言うのを難しい言葉でイミュータブル immutable と言います。 タプル tuple はイミュータブル immutable です。

「変更できる」と言うのを難しい言葉でミュータブル mutable と言います。 リスト list はミュータブル mutable です。

# 1.2. メソッドの数の違い

タプルは変更できないのでメソッドが、たったの2つしかありません。

print(*(attr for attr in dir(tuple) if '__' not in attr ), sep="\n")
>>> print(*(attr for attr in dir(tuple) if '__' not in attr ), sep="\n")
count
index
>>> 

反対にリストは変更できるため、その操作に合わせてメソッドがたくさんあります。

print(*(attr for attr in dir(list) if '__' not in attr ), sep="\n")
>>> print(*(attr for attr in dir(list) if '__' not in attr ), sep="\n")
append
clear
copy
count
extend
index
insert
pop
remove
reverse
sort
>>> 

# 2. 変更できないことに意味があるのか?

ざっくり言えば、可読性と安全性が上がります。 変更ができない、副作用のないことは一般に可読性と安全性をあげると言われています。 たかだか変更できないくらいのことに、どれくらいの意味があるのか、以下の記事でご紹介させていただきました。

# 3. タプルとリスト、どっちを使えばいいの?

上記の理由から、基本的には変更する必要がない場合は、 タプル tuple が使える場合には、 リスト list ではなくタプル tuple を使うべきだと考えます。

# 4. タプルの元々の意味、意図

tuple は、言うなればユーザ定義クラスの一種です。 わざわざユーザ定義クラスを作るほどではないなという時に使います。  タプルtuple  で厳しくなったら  辞書dict  を用います。 辞書 dict でも厳しくなったら  ユーザ定義クラス class   を定義します。

# 1. タプルの本来の意味(タプルから辞書、辞書からクラス)
class Person(object):
    def __init__(self, name, age):
        self.name, self.age = name, age

person1 = ('岩倉玲音', 14)                 # 1. tuple
person2 = {'name': '岩倉玲音', 'age': 14}  # 2. dict
person3 = Person('岩倉玲音', 14)           # 3. class

person1[0]                                 # 1. tuple
person2['name']                            # 2. dict
person3.name                               # 3. class

なぜタプルとリストという別のデータ型が用意されているのですか?
 リストとタプルは 、 多くの点で似ていますが、一般には本質的に  異なる方法で使われます  タプルは、Pascal のレコードや C の構造体と同様なものと考えられます。  型が異なっても良い関連するデータの小さな集合で、グループとして演算されます。 例えば、デカルト座標は 2 つや 3 つの数のタプルとして適切に表せます。

一方、 リストは、もっと他の言語の配列に近いものです。  全て同じ型の可変数のオブジェクトを持ち、それらが一つ一つ演算される傾向にあります。 例えば、 os.listdir('.') はカレントディレクトリ内にあるファイルの文字列表現のリストを返します。 この出力を演算する関数は一般に、ディレクトリに一つや二つの別のファイルを加えても壊れません。

ABC 言語の Compounds 型に由来しているらしいです。 PUT value IN name で代入になります。 lst[0] のような添字表記 subscription で参照することはできなかったみたいです。

Compounds - ABC: Some Simple Examples

Compounds are like records or structures, but without field names:

>>> PUT ("Square root of 2", root 2) IN c
>>> WRITE c
("Square root of 2", 1.414213562373095)
>>> PUT c IN name, value
>>> WRITE name
Square root of 2
>>> WRITE value
1.414213562373095

書籍 Fluent Python 2.11 参考文献の末尾にあった「タプルの秘密」から知りました。

こうした制限は、コンパウンド型の主たる目的を明確にしています。 つまりそれは、フィールド名のないただのレコードではないか。 私はそうGuidoに話しました。 彼は「タプルをシーケンスみたいに動作させるようにするのはハックだったよ」と答えました。
タプルの秘密 - Fluent Python

タプルという言葉そのものの意味はこちらになります。数学から引っ張ってきた用語だったんですね。

タプル - Wikipedia
タプルまたはチュープル(英: tuple)とは、複数の構成要素からなる組を総称する一般概念。 数学や計算機科学などでは通常、順序付けられた対象の並びを表すために用いられる。

# 5. 型アノテーション

この辺りの雰囲気は 型アノテーション を使うと伝わりやすいかもしれません。 伝わらないかもしれません。 知らなくても大丈夫なので気楽に読み流してください。

このコードを...

lain  = ('岩倉玲音', 14, False)
print(lain)

yaruo = ('やる夫', 20)
print(yaruo)

型付けすると、こんな感じになります。

#
# 新しい型を定義します。
#
from typing import NewType
Name   = NewType('Name',   str )
Age    = NewType('Age',    int )
Gender = NewType('Gender', bool)

from typing import Tuple
Person = NewType('Person',
    Tuple[
        Name,
        Age,
        Gender
])

#
# 変数を定義します。
#
lain:  Person
yaruo: Person

#
# 変数に代入します。
#
lain = Person((
    Name('岩倉玲音'),
    Age(14),
    Gender(False)
))
print(lain)
# ('岩倉玲音', 14, False)
#     すごそうなことをしているように見えますが...
#     変数 lain に代入されているのは
#     たんなる tuple でしかありません。
#     型を明示しないと mypy に弾き返されます。

yaruo = Person((
    Name('やる夫'),
    Age(20),
    # Gender(True),  <--- 1つ抜いておくと...
))
print(yaruo)

mypy で型検査するとエラーで怒られます。 Person は要素が3つ必要なのに1つ足りないよ、と怒られています。

$ mypy sample.py
sample.py:23: error:
Argument 1 to "Person" has incompatible type "Tuple[Name, Age]";
expected "Tuple[Name, Age, Gender]"
$

ちなみに実行はできます。

$ python sample.py
('岩倉玲音', 14, False)
('やる夫', 20)
$

この辺りの tuple に関する挙動は、 この記事から知ることができました。ありがとうございます。

# 6. まとめ

タプルはイミュータブルなリストです。 イミュータブルにすることは、 コードの可読性や安全性を向上させます。

また Python の tuple は簡易的なクラスを作成することを意図していた ABC 言語の Compounds 型に由来しています。