IT

Pythonのリスト・辞書・タプル・セットの違い

前回までにPythonにおいて重要な位置づけのリスト・辞書・タプル・セットについて紹介しました。ここではそれらの特徴や性質の違いをまとめ、補足としていくつか説明したいと思います。

特徴の比較

リスト・辞書・タプル・セットについて比較しました。下表を参照ください。

リスト 辞書 タプル セット
全ての型を許容する
異なる型の値を混在できる
後から値の更新・削除ができる ×
値の重複を許す ×
他のプログラミング言語でいうと
動的配列 コレクション 静的配列 集合

どれも基本的にはどの型のオブジェクトでも格納でき、異なる型が混在してもよいこととなっています。ただし、セットのみ値の重複を許していません。また、オブジェクトの操作に関してはタプルは後から値を更新・削除することはできず、セットはfrozensetで作成したものであれば、同様にできません。

コピーの挙動について

各オブジェクトのトピックでは触れていなかったオブジェクトのコピーについて紹介します。pythonのコピーは少し特殊で「各値をコピーするものの、その値の参照先まではコピーしない」、「値の参照を全てたどりデータをコピーする」というものがあります。前者のコピーを『浅いコピー』、後者のコピーを『深いコピー』と呼びます。ここでは4つのオブジェクトのこの2種類のコピーについて説明をします。

浅いコピー

浅いコピーとは各値をコピーするものの、その値が参照するデータ(リストの入れ子など)はコピーしない方法です。このコピー方法でコピーしないと、参照先のアドレスにある実データを変更したら、コピーしたオブジェクトの中身は全て変わります。

リストの浅いコピー(リスト[:]とlist(リスト))

リストのコピーは『リスト[:]』や『list(リスト)』を使います。


>>> a = [1,2,3]
>>> b = a[:]
>>> b
[1, 2, 3]
>>> b[1] = 'A'
>>> b
[1, 'A', 3]
>>> a
[1, 2, 3]

このようにリストbの値を変更してもリストaの値には影響がありません。これは浅いコピーによって各値をアドレスではなく、実データとしてコピーしてきているからです。

辞書の浅いコピー(dict(辞書))

辞書の浅いコピーは『dict(辞書)』を使います。


>>> a = { 1:'java',2:'python'}
>>> b = dict(a)
>>> b
{1: 'java', 2: 'python'}

 

タプルの浅いコピー

タプルは『tuple(タプル)』で浅いコピーができますが、そもそも値の変更ができないため、不要です。


>>> a = (1,2,3)
>>> b =tuple(a)
>>> b
(1, 2, 3)

 

セットの浅いコピー

セットは『set(セット)』でコピーできますが、変更不可能なオブジェクトしか値に持てないため、不要です。


>>> a = set([1,2,3])
>>> b = set(a)
>>> b
set([1, 2, 3])

 

深いコピー

深いコピーは値の参照を全てさかのぼってデータをコピーします。浅いコピーではできなかったリストの入れ子なども参照先の値を変更しても参照元の値が変化することなくできます。なお、深いコピーはcopyモジュールを使います。

リストの深いコピー(copy.deepcopy(リスト))

リストの深いコピーは『copy.deepcopy(リスト)』を使います。


>>> import copy
>>> a = [1,[2,2],3]
>>> b = copy.deepcopy(a)
>>> b
[1, [2, 2], 3]
>>> b[1].append(2)
>>> b
[1, [2, 2, 2], 3]
>>> a
[1, [2, 2], 3]

 

辞書の深いコピー(copy.deepcopy(辞書))

辞書もリストと同様に『copy.deepcopy(辞書)』を使います。値のリストなども参照元に影響を及ぼさずに扱えます。


>>> import copy
>>> a = { 1:'java',2:['python','C++']}
>>> b = copy.deepcopy(a)
>>> b
{1: 'java', 2: ['python', 'C++']}
>>> b[2].append('VB')
>>> b
{1: 'java', 2: ['python', 'C++', 'VB']}
>>> a
{1: 'java', 2: ['python', 'C++']}

 

タプルの深いコピー

タプルの深いコピーも『copy.deepcopy(タプル)』で可能ですが、値の更新ができないため、不要です。


>>> import copy
>>> a = (1,[2,2],3)
>>> b = copy.deepcopy(a)
>>> b
(1, [2, 2], 3)

 

セットの深いコピー

セットの深いコピーも『copy.deepcopy(セット)』でできますが、変更不可能なオブジェクトしか値に持たないため、不要です。


>>> import copy
>>> a = set([1,(2,2),3])
>>> b = copy.deepcopy(a)
>>> b
set([1, 3, (2, 2)])

 比較演算子の意味合いの違い

リスト・辞書・タプル・集合は比較演算子を使ってオブジェクトの比較をすることができます。比較演算子は等価比較、大小比較、is比較です。

リストの比較

リストの比較の意味合いは以下となります。

・等価比較・・・リスト内の値が全て等しいか比較する
・大小比較・・・リスト内のそれぞれの値を左から比較する
・is比較・・・オブジェクトが同じかを比較する(値が全て同じだからと言って同じオブジェクトではない)

辞書の比較

辞書の比較の意味合いは以下となります。

・等価比較・・・キーと値のペアが全て同じか比較する
・大小比較・・・キーの数が多いかを比較する
・is比較・・・オブジェクトが同じかを比較する(値が全て同じだからと言って同じオブジェクトではない)

タプルの比較

タプルの比較の意味合いは以下となります。
・等価比較・・・タプル内の値が全て等しいか比較する
・大小比較・・・タプル内のそれぞれの値を左から比較する
・is比較・・・オブジェクトが同じかを比較する(値が全て同じだからと言って同じオブジェクトではない)

セットの比較

・等価比較・・・セット内の値が全て等しいか比較する
・大小比較・・・部分集合かを比較する(集合A>集合Bは、集合Bは集合Aの部分集合かを比較している」)
・is比較・・・オブジェクトが同じかを比較する(値が全て同じだからと言って同じオブジェクトではない)

まとめ

リスト・辞書・タプル・集合のそれぞれのコピーの違いは下表となります。

リスト 辞書 タプル セット
浅いコピー list(リスト) dict(辞書) 不要 不要
深いコピー copy.deepcopy(リスト) copy.deepcopy(辞書) 不要 不要

また、比較の意味合いは下表となります。

リスト 辞書 タプル セット
等価比較 値が全て同じか キーと値のペアが全て同じか 値が全て同じか 値が全て同じか
大小比較 値を左から比較し大きいか キーの数が多いか 値を左から比較し大きいか 部分集合か
is比較 同じオブジェクトか 同じオブジェクトか 同じオブジェクトか 同じオブジェクトか

以上。