はじめに
Python の変数は「箱」ではなく「参照(名前タグ)」だとよく言われますが、
実際には Python のオブジェクトモデル・名前空間・可変性 まで理解すると、
その意味がもっとクリアに見えてきます。
本記事では、Python の変数を“プロの視点”で深掘りし、
「なぜ、こう動くのか」までを直感的に説明します。
1. 変数とは?Python 的には「名前(label)」
Python の変数とは:
オブジェクト(値)に貼られた名前(label)。
値そのものではなく “オブジェクトを指す参照”。
x = 10
これは「10 を x に入れる」ではなく、
x ──→ [10]
という「名前をオブジェクトにバインドする」という操作。
C や Java のプリミティブのような “箱モデル” ではない。
2. Python における「オブジェクト」について
Python では、すべてがオブジェクト。
整数・文字列・リスト・関数・クラス、全部同じ概念体系で扱われる。
オブジェクトには以下がある:
- 値(実データ)
- 型(type)
- 識別子(id)
- 参照カウンタ(メモリ管理のため)
type()、id() はデバッグの最強ツール。
x = 10
print(id(x), type(x))
3. 代入(assignment)は「コピー」ではなく「新しい参照の貼り付け」
a = [1, 2, 3]
b = a
これは値コピーではなく、
a ──┐
↓
[1,2,3]
↑
b ──┘
b は a と同じオブジェクトを見る。
4. 可変(mutable) vs 不可変(immutable)
ここが Python 変数の理解の“核心”。
◼ 不可変(immutable)
- int
- float
- str
- tuple
- frozenset
変更できない。
"変わる" ように見える処理は、実際には「新オブジェクト生成」。
x = 10
y = x
x += 1
# x と y は完全に別物
# y ─→ [10]
# x ─→ [11] (新しく作られた)
◼ 可変(mutable)
- list
- dict
- set
中身を書き換える操作を行うと 同じオブジェクトが変更される。
a = [1, 2, 3]
b = a
b.append(4)
# a ───┐
# ↓
# [1,2,3,4] ← オブジェクト本体が変更される
# ↑
# b ───┘
5. Python の代入は「名前 → オブジェクト」の紐づけ操作
Python の assignment の実態は:
<名前> = <式の評価結果>
式が評価され、オブジェクトが作られ、
その オブジェクトに名前がバインドされる。
❌ 値をコピーするのではない
⭕ 「名前を貼る」
6. 「同一性」と「等価性」は別物
| 比較 | 意味 | 判定 |
|---|---|---|
is |
同じオブジェクトか(参照先が同じ) | identity |
== |
値が等しいか | equality |
a = [1,2]
b = [1,2]
print(a == b) # True(値が同じ)
print(a is b) # False(別オブジェクト)
Python の参照モデルを理解するには 最重要の2つ。
7. 変数と名前空間(namespace)
Python の変数は 名前空間(dict)に格納されるキー でもある。
例:関数の中
def func():
x = 10
print(locals())
func()
出力:
{'x': 10}
Python の変数は「名前 → オブジェクト」を dict で管理する仕組み。
8.スコープ(LEGB ルール)
Python の変数の解決は、
- Local(関数内)
- Enclosed(内側の関数スコープ)
- Global(モジュール)
- Built-in(組み込み名)
この順に名前を探す。
図解すると:
Local → Enclosed → Global → Built-in
9. 初心者が最もハマる落とし穴(参照バグ)
9.1 デフォルト引数(mutable)
def f(x=[]):
x.append(1)
return x
print(f()) # [1]
print(f()) # [1, 1]
print(f()) # [1, 1, 1]
print(f()) # [1, 1, 1, 1]
これは 永遠に同じリストが使われ続ける。
9.2 list のコピーを忘れて破壊
b = a # 参照を共有してしまう
安全策:
b = a.copy()
# または b = list(a)
# または b = a[:](スライス)
参考として深いコピーは copy.deepcopy()。
まとめ
- Python の変数は “名前”であって箱ではない
- 変数はオブジェクトへ向く「参照(pointer 的なもの)」
- assignment は値コピーではなく「名前を貼り替える」
- メモリ上のオブジェクトは mutable / immutable によって挙動が異なる
- スコープは LEGB に従って解決される
- namespace(dict)に名前とオブジェクトが格納される
- 同一性(is)と等価性(==)は完全に別物
Python の変数は、言語の基本だけど実は極めて深い。
ここを理解すると、Python の“気持ち良い書き方”が一気に見えてくる。