#### 変数は箱である?
`a = 1` と書いたら、箱 a に $1$ を入れる

`b = a` と書いたら、箱 a に入っている $1$ をコピーして箱 b に入れる

というのはよくありそうな説明ですが、 Python の実態に即していません。実際、リストを使った時に混乱を招くことになります。
```python=
a = [1, 2, 3]
b = a
# a を変更すると b も変更される
a[0] = 0
print(b)
```
#### 変数はデータへのタグ付けである
実態に即した説明をしてみましょう。
`a = 1` と書いたら、**$1$ というデータを作り**、タグ a がそのデータを指すようにする

`b = a` と書いたら、タグ b が「タグ a が指すデータ」を指すようにする

#### リストの場合
試しにリストの例もこの形で表現してみましょう。
```python=
a = [1, 2, 3]
b = a
# a を変更すると b も変更される
a[0] = 0
print(b) # [0, 2, 3]
```
リスト `[1, 2, 3]` を作るには、まず整数 $1, 2, 3$ の入ったデータを作る必要があります。

そうしたら、
- 0 番目の要素が整数 $1$ の入ったデータを指し、
- 1 番目の要素が整数 $2$ の入ったデータを指し、
- 2 番目の要素が整数 $3$ の入ったデータを指す
リストを作ります。

最後に、このリストを指すタグ a を作ります。

これで `a = [1, 2, 3]` ができました。
続いて `b = a` をすると、タグ b が「タグ a が指すデータ」を指すようになります。

この状態で、`a[0] = 0` をやってみましょう。
まず、整数 $0$ の入ったデータを作ります。

そうしたら、`a[0]` (赤い部分) が今作ったデータを指すようにします。

`a[0]` が $0$ になりましたが、同時に `b[0]` も $0$ になっていることがわかります。
#### 二次元配列の罠
```python=
a = [[0] * 3] * 3
# a[0] も a[1] も a[2] も同じリストなので、a[0] を変更すると a[1] と a[2] も同時に変更される
a[0][0] = 1
print(a[1]) # [1, 0, 0]
```
よくあるやつですね。これを実行する前に、`*` の仕様を見ておきましょう。
1 次元の場合をやってみます。
```python=
[0, 1] * 3
```
まず、整数 $0, 1$ の入ったデータを作ります。

次に、リスト `[0, 1]` を作ります。

このリストに対し `* 3` を行います。

$0, 1$ はコピーされず、同じ $0$ と $1$ に 3 本ずつ矢印が引かれたリストができます。
さて、本題に戻って
```python=
a = [[0] * 3] * 3
# a[0] も a[1] も a[2] も同じリストなので、a[0] を変更すると a[1] と a[2] も同時に変更される
a[0][0] = 1
print(a[1]) # [1, 0, 0]
```
を実行してみましょう。まず、
- `a = [[0] * 3] * 3` をするための
- `[[0] * 3] * 3` を作るための
- `[[0] * 3]` を作るための
- `[0] * 3` を作るための
- `[0]` を作るための
- `0` を作ります。

`[0]` を作ります。

`[0] * 3` を作ります。

`[[0] * 3]` を作ります。

`[[0] * 3] * 3` を作ります。

できた `[[0] * 3] * 3` を指すタグ a を作ります。

`a[0]` も `a[1]` も `a[2]` も同じリストを指していますね。
`a[0][0] = 1` をすると、

`a[1][0]` も `a[2][0]` も $1$ になってしまいます。
#### mutable と immutable
Python の型は大きく mutable (可変) なものと immutable (不変) なものに分けることができます。
| 例 | |
| --- | --- |
| immutable | int, float, bool, str, tuple など |
| mutable | list, set, dict, collections.deque など |
immutable な型のデータは、一度作られるとそれ以降変わることがありません。
```python=
a = 1
b = a
a += 2
```
を考えてみましょう。
まず、`a = 1` で、整数 $1$ の入ったデータを作り、タグ a をつけます。

`b = a` で、タグ b が「タグ a が指すデータ」を指すようにします。

ここで、`a += 2` をします。まず、整数 $2$ を作って…

タグ a の指す $1$ に $2$ を足して $3$ に変更したいのですが、int 型は一度作ると変更できないので、整数 $1 + 2 = 3$ を新たに作ります。

そして、タグ a の指す先を新たに作った $3$ に変更します。

このとき、`b` は $1$ のままです。
**immutable な型のデータは一度作ると変更できず、immutable な型の変数を変更しようとすると新しくデータが作られる** ことを覚えておきましょう。
もし、int 型が mutable であった場合はどうなるでしょうか?
`a += 2` をすると…

データの方が変更されて $3$ になります。

このとき、`b` も $3$ に変わってしまいます。
**mutable な型の変数を変更しようとするとデータの方が変更され、同じデータを指している別の変数も同時に変わってしまう** ことを覚えておきましょう。
#### 計算量の違い
mutable と immutable の違いは計算量の違いも生みます。
list の連結 `a += b` はデータの方を変更するので償却 $\Theta(|b|)$ 時間ですが、
str の連結 `a += b` はデータの方を変更できずコピーが必要なため、$\Theta(|a| + |b|)$ 時間になります。
したがって、list を $N$ 回連結する操作
```python=
a = []
for _ in range(N):
a += [1]
```
は $\Theta(N)$ 時間ですが、str を $N$ 回連結する操作
```python=
a = ""
for _ in range(N):
a += "1"
```
は $\Theta(N^2)$ 時間になってしまいます。