Pythonのミュータブル・イミュータブルとは?|型ごとの違いを整理

ソフトウェア
スポンサーリンク

はじめに

Pythonを勉強していると、

「ミュータブルとイミュータブル」

という言葉に出会うことがあります。

特に、

x = [1, 2, 3]
y = x

y.append(4)

print(x)

を実行すると、

[1, 2, 3, 4]

となるため、

y を変更したのに、なぜ x まで変わるの?」

と疑問に感じることがあります。

この動きを理解するうえで重要なのが、ミュータブル(mutable)とイミュータブル(immutable)という考え方です。

簡単に言えば、

ミュータブル:オブジェクトそのものを変更できる
イミュータブル:オブジェクトそのものを変更できない

という違いです。

この記事では、Pythonでよく使う型を中心に、

  • ミュータブルとイミュータブルとは何か
  • どの型のオブジェクトがミュータブルなのか
  • なぜ list は変更できて、intstr は変更できないのか
  • tuple が少しややこしい理由

について整理していきます。

この記事でわかること

この記事では、次の内容の理解を目指します。

  • ミュータブルとイミュータブルの意味
  • Pythonの代表的な型のオブジェクトがミュータブル・イミュータブルのどちらなのか
  • intstr のオブジェクトがイミュータブルである理由
  • listdict のオブジェクトがミュータブルである理由
  • tuple のオブジェクトがイミュータブルでも注意が必要な理由
  • ミュータブル・イミュータブルと変数の参照の関係

1. ミュータブルとイミュータブルとは?

まずは言葉の意味から確認しましょう。

ミュータブルには「変更可能」という意味があります。

一方、イミュータブルは「変更できない」という意味です。

Pythonでは、オブジェクトについて、

そのオブジェクト自身の状態を変更できるか?

という観点で、ミュータブルとイミュータブルを考えます。

▶ Pythonの変数・オブジェクト・参照について詳しく知りたい方は、次の記事を参考にしてください。
Pythonの変数は「箱」ではない?|オブジェクトと参照を理解する
はじめにPythonを勉強していると、変数についてこんなふうに考えることがあると思います。x = 10「x という箱を用意して、そこに 10 を入れる」入門書では、このようなイメージで説明されることもあります。もちろん、最初にPythonを...

ミュータブル

ミュータブルなオブジェクトは、オブジェクトそのものを変更できます。

代表的なものには、

  • list
  • dict
  • set
  • bytearray

などがあります。

イミュータブル

イミュータブルなオブジェクトは、オブジェクトそのものを変更できません。

代表的なものには、

  • int
  • float
  • bool
  • str
  • tuple
  • bytes

などがあります。

2. Pythonの型を一覧で整理

まずは代表的な型を一覧で見てみましょう。

mutable / immutable
bool immutable
int immutable
float immutable
complex immutable
str immutable
tuple immutable
bytes immutable
list mutable
set mutable
dict mutable
bytearray mutable

ざっくり覚えるなら、

listdictset のオブジェクトはミュータブル
intfloatcomplexbool などの数値系、strtuplebytes のオブジェクトはイミュータブル

と覚えておくとよいでしょう。

ただし、単純に暗記するだけではなく、この違いがPythonのコードにどのように影響するのかを理解することが重要です。

3. int のオブジェクトはイミュータブル

まず、もっとも身近な例として整数を見てみましょう。

x = 10

x10 という整数オブジェクトを参照しています。

ここで、

x = 20

とすると、

10 というオブジェクトが 20 に変わった」

わけではありません。

x が参照するオブジェクトが変わっています。

イメージすると、

整数オブジェクトは参照先が変更される

です。

10 という整数オブジェクトそのものを変更したわけではありません。

つまり、int のオブジェクトはイミュータブルです。

4. 「x = 10」は変更ではない

ここで、もう一つ重要なポイントを確認しておきましょう。

x = 10
x = 20

見た目だけを見ると、

x の値を 10 から 20 に変更した

ように感じます。

しかし、Pythonでは、

x の参照先が変わった

と考えるほうが正確です。

つまり、10 という整数オブジェクトそのものを変更したのではありません。

この「変数の参照先を変更すること」と「オブジェクトそのものを変更すること」の違いが、ミュータブル・イミュータブルを理解するうえで重要になります。

Pythonの変数とオブジェクトについては、次の記事で詳しく解説しています。

Pythonの変数は「箱」ではない?|オブジェクトと参照を理解する
はじめにPythonを勉強していると、変数についてこんなふうに考えることがあると思います。x = 10「x という箱を用意して、そこに 10 を入れる」入門書では、このようなイメージで説明されることもあります。もちろん、最初にPythonを...

5. list のオブジェクトはミュータブル

一方、list のオブジェクトはミュータブルです。

例えば、

numbers = [1, 2, 3]

というリストを作ったとします。

そして、

numbers.append(4)

とすると、

[1, 2, 3]

だったリストが、

[1, 2, 3, 4]

になります。

ここでは、numbers が参照している同じリストオブジェクトそのものが変更されています。

イメージすると、

リストオブジェクトそのものが変更される

となります。

このように、list はオブジェクトの状態を変更できるミュータブルな型です。

6. なぜ「x まで変わる」のか?

ここで、よくある疑問を考えてみましょう。

x = [1, 2, 3]
y = x

y.append(4)

print(x)
print(y)

結果は、

[1, 2, 3, 4]
[1, 2, 3, 4]

です。

なぜでしょうか?

理由は、xy が同じリストオブジェクトを参照しているからです。

y = x

ここで、

y.append(4)

を実行します。

すると、

y.append(4)

となります。

y が参照しているリストを変更した結果、同じリストを参照している x から見ても変更後の状態になっているわけです。

これが、ミュータブルなオブジェクトを扱うときに注意したいポイントです。

7. str のオブジェクトもイミュータブル

文字列のオブジェクトもイミュータブルです。

例えば、

text = "Python"

とします。

ここで、文字列の一部だけを変更しようとして、

text[0] = "J"

とすると、エラーになります。

文字列オブジェクトそのものを変更することはできないからです。

では、

text = "Java"

ならどうでしょうか。

これは問題ありません。

ただし、これは「Python」という文字列を「Java」に変更したわけではありません。

text が参照する文字列オブジェクトを変更したと考えます。

つまり、

text =

から

text =

へと参照先が変わったということです。

8. dict と set のオブジェクトもミュータブル

list のオブジェクト以外にも、代表的なミュータブルな型があります。

dict

辞書のオブジェクトはミュータブルです。

user = {
    "name": "Taro",
    "age": 20
}

例えば、

user["age"] = 21

とすると、辞書の内容を変更できます。

{
    "name": "Taro",
    "age": 20
}

から

{
    "name": "Taro",
    "age": 21
}

に変わります。

同じ dict オブジェクトの状態が変更されています。

set

set のオブジェクトもミュータブルです。

numbers = {1, 2, 3}

に対して、

numbers.add(4)

とすると、

{1, 2, 3}

から、

{1, 2, 3, 4}

へ変更できます。

9. tuple のオブジェクトはイミュータブル

ここで少し注意したいのが tuple です。

tuple のオブジェクトはイミュータブルです。

numbers = (1, 2, 3)

に対して、

numbers[0] = 10

のように要素を変更することはできません。

つまり、

tuple そのものの状態は変更できない

ということです。

ただし、ここには少しややこしいポイントがあります。

10. 「tuple の中身」には注意

例えば、次の tuple を考えてみましょう。

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

tuple のオブジェクト自体はイミュータブルです。

しかし、tuple の中に入っているのは list です。

list のオブジェクトはミュータブルでした。

そのため、

data[0].append(5)

は実行できます。

結果は、

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

となります。

tuple なのに変更できた?」

と思うかもしれません。

しかし、変更されたのは tuple そのものではありません。

tuple の中に入っている list オブジェクトが変更されたのです。

イメージすると、最初は

tupleの値は参照

ですが、

data[0].append(5)

によって、

tupleの要素がミュータブルなら変更できる

となります。

ここから、

tuple は、保持している要素を別のオブジェクトに置き換えることはできない。
しかし、tuple の要素が list のようなミュータブルなオブジェクトなら、要素のオブジェクトを変更することはできる。

という意味であることがわかります。

11. ミュータブル・イミュータブルをどう覚える?

ここまでの内容を整理すると、代表的な型は次のようになります。

イミュータブル

bool
int
float
complex
str
tuple
bytes

ミュータブル

list
dict
set
bytearray

まずは、この程度を覚えておけば十分です。

ただし、単純に一覧を暗記するより、

そのオブジェクト自体を変更できるか?

と考える癖をつけるほうが重要です。

例えば、

x = [1, 2, 3]

なら、

list のオブジェクトだからミュータブル

と判断できます。

x = "Python"

なら、

str のオブジェクトだからイミュータブル

と判断できます。

12. ミュータブル・イミュータブルと代入の関係

最後に、今回の記事の最初に出てきたコードに戻ってみましょう。

x = [1, 2, 3]
y = x

y.append(4)

xy は同じ list オブジェクトを参照しています。

そして list はミュータブルなので、

y.append(4)

によって、そのリスト自体を変更できます。

そのため、x から見ても、

[1, 2, 3, 4]

になっています。

一方、int なら、

x = 10
y = x

x = 20

としても、

x → 20, y → 10

となります。

これは 10 という整数オブジェクトを変更したのではなく、x の参照先が変わったからです。

このように、

「変数がどのオブジェクトを参照しているか」

と、

「そのオブジェクトがミュータブルなのかイミュータブルなのか」

を組み合わせて考えると、Pythonの動きを理解しやすくなります。

まとめ

Pythonのミュータブル・イミュータブルについて整理しました。

ミュータブル

ミュータブルなオブジェクトは、オブジェクトそのものを変更できます。

代表的な型は、

list
dict
set
bytearray

などです。

イミュータブル

イミュータブルなオブジェクトは、オブジェクトそのものを変更できません。

代表的な型は、

bool
int
float
complex
str
tuple
bytes

などです。

そして重要なのは、

「変数の値を変更した」のか、「オブジェクトそのものを変更した」のかを区別すること

です。

例えば、

x = 10
x = 20

では、10 という整数オブジェクトを変更したのではなく、x の参照先が変わっています。

一方、

x = [1, 2, 3]
x.append(4)

では、x が参照しているリストオブジェクトそのものが変更されています。

Pythonのミュータブル・イミュータブルを理解するときは、「そのオブジェクト自身を変更できるか?」と考える。

そして、これを以前の記事で説明した「Pythonの変数は箱ではなく、オブジェクトを参照する名前」という考え方と組み合わせると、リストや辞書を扱うときの「なぜこうなるの?」がかなり理解しやすくなります。

関連記事

Pythonの変数・オブジェクト・参照について詳しく解説しています。

Pythonの変数は「箱」ではない?|オブジェクトと参照を理解する
はじめにPythonを勉強していると、変数についてこんなふうに考えることがあると思います。x = 10「x という箱を用意して、そこに 10 を入れる」入門書では、このようなイメージで説明されることもあります。もちろん、最初にPythonを...

関連書籍

Pythonの文法だけでなく、オブジェクトやデータモデルなど、Pythonの仕組みをもう少し深く理解したい人には『入門 Python 3』もおすすめです。

Amazon.co.jp

コメント

タイトルとURLをコピーしました