目的
Pythonの組み込み型である[リスト]と[タプル]の違いについて理解を深めるため。
リストとタプルの違い
下記の出力結果をみる限り()と[]の違いしかありません。
定義方法やデータへのアクセス方法も似ています。
リスト
他のプログラミング言語の「配列」の存在に近い。
week_list = ['月曜日', '火曜日', '水曜日']
print(type(week_list))
# <class 'list'>
print(week_list[0])
# '月曜日'
print(week_list[1:])
# ['火曜日', '水曜日']
タプル
Python における「タプル」とは、複数のデータを一直線に並べた「コレクション」タイプのデータ型です。
week_tuple = ('月曜日', '火曜日', '水曜日')
print(type(week_tuple))
# <class 'tuple'>
print(week_tuple[0])
# '月曜日'
print(week_tuple[1:])
# ('火曜日', '水曜日')
リストとタプルの明確な違い
では、リストとタプルの違いとはなんでしょうか。
それはリストはオブジェクト作成後にオブジェクトidの変更なしに要素を追加・変更・削除が可能(ミュータブル)ですが、タプルはオブジェクト作成後にオブジェクトidの変更なしに要素を追加・変更・削除が不可能(イミュータブル)でないということです。
イミュータブルとは
イミュータブルとはオブジェクトidの変更なしに追加・変更・削除がでいないと上記で説明しましたが勘違いされやすいポイントが二つあります。
1.
Q. イミュータブルオブジェクトは要素を変更できないのか?
A. オブジェクトidが変わってしまうが要素を変更可能
# リスト型がミュータブルであることを確認
fruits_list = ['みかん', 'りんご']
print(id(fruits_list))
# 4417466768
fruits_list += ['バナナ', 'パイナップル']
print(id(fruits_list))
# 4417466768
# 要素を追加したがオブジェクトidが変わっていない
# タプルがイミュータブルであることを確認
fruits_tuple = ('みかん', 'りんご')
print(id(fruits_tuple))
# 4417176592
fruits_tuple += ('バナナ', 'パイナップル')
print(id(fruits_tuple))
# 4417197744
# 要素を追加したためオブジェクトidが変化
イミュータブルオブジェクトは累算代入(
+=
など)の演算メソッド(__iadd__
など)を持っておらず、通常の加算演算(__add__
)に置き換えられます。
累算代入演算子を呼び出した時にリストなどのミュータブルオブジェクトは.__iadd__
がイミュータブルオブジェクトは.__add__
が呼び出されていたので結果としてオブジェクトidの振る舞いに違いが出ていたのですね。
2.
Q. オブジェクトidを変えずに要素を変えることは不可能なのか?
A. イミュータブルの要素にミュータブルな要素を持つことで要素の追加・変更・削除は可能
# dictを要素に持つタプルを定義
cards_tuple = ({'mark': 'ハート', 'number': '7'}, {'mark': 'スペード', 'number': '2'})
print(id(cards_tuple))
# 4417441456
# dict を変更する
cards_tuple[0]['mark'] = 'スペード'
cards_tuple[1]['number'] = '13'
print(cards_tuple)
print(id(cards_tuple))
# 4417441456
# 変更後もオブジェクトidが変わっていない
まとめ
基本的にはリストを使っていき、イミュータブルであることが利益となる場合にタプルを使用するようにしていこうと思いました。
tupleには他にもhashableであるという特徴もあるようです。
参考
I'm able to use a mutable object as a dictionary key in python. Is this not disallowed?
https://docs.python.org/ja/3/reference/datamodel.html#object.iadd