わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

Pythonのタプルとリストの違いについて

 いきなりですが問題です.Pythonで書かれた,以下のプログラムコードをご覧ください.

a = (1, 2, 3)
b = a
c = [1, 2, 3]
d = c
print(a, b, c, d)
a = a + (4,)
c.append(4)
print(a, b, c, d)
a += (5,)
c += [5]
print(a, b, c, d)
a = a + (6,)
c = c + [6]
print(a, b, c, d)

 最初にprint関数を呼び出したときの出力は,次の通りです.

(1, 2, 3) (1, 2, 3) [1, 2, 3] [1, 2, 3]

 このときの,変数aからdまでの状況を最も適切に表したのは,以下の3つの画像のどれでしょうか.

 さっそくですが解答です.最も適切に表したのは,以下の画像です.

 aとbは,出力により(1, 2, 3)となるタプルを参照し,cとdは,[1, 2, 3]となるリストを参照しています.タプルとリストの違いは,例えば以下より読むことができます.

 冒頭のプログラムでは,「print(a, b, c, d)」が4回実行されます.そのたびに,4つの変数が参照する内容(データ構造)を出力します.2回目の呼び出しの出力は,次のようになります.

(1, 2, 3, 4) (1, 2, 3) [1, 2, 3, 4] [1, 2, 3, 4]

 ここから,タプルとリストの違いを知ることができます.まず,1回目と2回目のprint関数の呼び出しの間に書かれた「a = a + (4,)」を実行することで,aとbとで参照するタプルが変わります.aは,新たに作られたタプル(1, 2, 3, 4)を参照することになるのに対し,bは変わりません.
 リストについては,「c.append(4)」を実行することで,cが参照するリストの末尾に4が追加され,出力としては[1, 2, 3, 4]となります.要素が増えたこのリストを,cも,dも,参照しています.リストの状態は変わるけれども,その参照は変わらない,ということです.
 図は次の通りとなります.

 3回目の呼び出しの出力は,次のようになります.

(1, 2, 3, 4, 5) (1, 2, 3) [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]

 タプルへの値の追加は,2回目の前のときと同様です*1.リストへの値の追加は,「c += [5]」に変わりましたが,要素数が5になり,cも,dもこのリストを参照しているのは,変わりません.図は次の通りです.

 最後の呼び出しの出力には,少し注意が必要です.

(1, 2, 3, 4, 5, 6) (1, 2, 3) [1, 2, 3, 4, 5, 6] [1, 2, 3, 4, 5]

 タプルへの値の追加は,2回目・3回目と同様です.リストへの値の追加による振る舞いが,変わりました.「c + [6]」により,[1, 2, 3, 4, 5, 6]となる新たなリストが作られ,「c = そのリスト」により参照します.その一方で,変数dの参照は変わらず,出力としては[1, 2, 3, 4, 5]です.図は次の通りです.

 ここまでをまとめると,以下の通りとなります.

  • 「b = a」により,aとbは同じタプルを参照している.
  • 「a = a + (4,)」を実行することで,aとbとで参照するタプルが変わる.
  • 「d = c」により,cとdは同じリストを参照している.
  • 「c.append(4)」や「c += [5]」を実行しても,cとdは同じリストを参照している.
  • 「c = c + [6]」を実行することで,cとdとで参照するリストが変わる.
  • 変数がリストを参照するとき,「変数 += 他のリスト」と「変数 = 変数 + 他のリスト」は異なる.

*1:ただし1点だけ注意することがあります.(1, 2, 3, 4)で表されるタプルを,aもbも参照しなくなりました.あとで示す図は,(1, 2, 3, 4)のタプルが(1, 2, 3, 4, 5)になった,というのではなく,(1, 2, 3, 4)のタプルと別に,(1, 2, 3, 4, 5)のタプルが新たに作られて,aがそれを参照する,と考えないといけません.